Check-in [d756b0ea34]
Overview
Comment:Better handling for unapproved apps and dealing with non-RSA signing attempts
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d756b0ea343b5ea0663716ad63b57d8e3d4a772d
User & Date: rkeene on 2019-01-31 13:25:45
Other Links: manifest | tags
Context
2019-01-31
13:29
Ensure externally connectable IDs are present check-in: e04736eb53 user: rkeene tags: trunk
13:25
Better handling for unapproved apps and dealing with non-RSA signing attempts check-in: d756b0ea34 user: rkeene tags: trunk
07:23
Improved SSH agent check-in: 43f92f8f98 user: rkeene tags: trunk
Changes

Modified build/chrome/ssh-agent.js from [f8ff078c88] to [2a1297f569].

1
2
3
4
5
6

7
8
9
10
11
12
13
/*
 * CACKey SSH Agent for ChromeOS
 */

cackeySSHAgentApprovedApps = [
	"pnhechapfaindjhompbnflcldabbghjo"

];

/*
 * SSH Element Encoding/Decoding
 */
function cackeySSHAgentEncodeInt(uint32) {
	var result;





|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * CACKey SSH Agent for ChromeOS
 */

cackeySSHAgentApprovedApps = [
	"pnhechapfaindjhompbnflcldabbghjo",
	"okddffdblfhhnmhodogpojmfkjmhinfp"
];

/*
 * SSH Element Encoding/Decoding
 */
function cackeySSHAgentEncodeInt(uint32) {
	var result;
180
181
182
183
184
185
186

187
188
189
190
191
192
193
		default:
			console.log("[cackeySSH] Unsupported public key type:", publicKey.type, "-- ignoring.");
	}

	if (resultKey) {
		result = {
			id: certObj.getSubjectString(),

			key: resultKey
		};
	}

	return(result);
}








>







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
		default:
			console.log("[cackeySSH] Unsupported public key type:", publicKey.type, "-- ignoring.");
	}

	if (resultKey) {
		result = {
			id: certObj.getSubjectString(),
			type: publicKey.type,
			key: resultKey
		};
	}

	return(result);
}

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
	});

	return(response);
}

async function cackeySSHAgentCommandSignRequest(request) {
	var keyInfo, data, flags;
	var certs, certToUse;
	var hashMethod, signedData, signedDataHeader, signRequest;
	var response;
	var flagMeaning = {
		SSH_AGENT_RSA_SHA2_256: 2,
		SSH_AGENT_RSA_SHA2_512: 4
	};








|







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
	});

	return(response);
}

async function cackeySSHAgentCommandSignRequest(request) {
	var keyInfo, data, flags;
	var certs, certToUse, certToUseType;
	var hashMethod, signedData, signedDataHeader, signRequest;
	var response;
	var flagMeaning = {
		SSH_AGENT_RSA_SHA2_256: 2,
		SSH_AGENT_RSA_SHA2_512: 4
	};

276
277
278
279
280
281
282

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297


298
299
300
301
302
303
304
305
306
307
308
309
310
























311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
	certs.forEach(function(cert) {
		var key;

		key = cackeySSHAgentEncodeCertToKeyAndID(cert.certificate);

		if (key.key.join() == keyInfo.join()) {
			certToUse = cert;

		}
	});

	/*
	 * If no certificate is found, return an error
	 */
	if (!certToUse) {
		console.info("[cackeySSH] Unable to find a certificate to match the requested key:", keyInfo);

		return(null);
	}

	/*
	 * Perform hashing of the data as specified by the flags
	 */


	if ((flags & flagMeaning.SSH_AGENT_RSA_SHA2_512) == flagMeaning.SSH_AGENT_RSA_SHA2_512) {
		hashMethod = "SHA512";
		data = await crypto.subtle.digest("SHA-512", new Uint8Array(data));
	} else if ((flags & flagMeaning.SSH_AGENT_RSA_SHA2_256) == flagMeaning.SSH_AGENT_RSA_SHA2_256) {
		hashMethod = "SHA256";
		data = await crypto.subtle.digest("SHA-256", new Uint8Array(data));
	} else if (flags == 0) {
		hashMethod = "SHA1";
		data = await crypto.subtle.digest("SHA-1", new Uint8Array(data));
	} else {
		console.info("[cackeySSH] Sign request with flags set to", flags, "which is unsupported, failing the request.");

		return(null);
























	}

	/*
	 * Sign the data
	 */
	signRequest = {
		hash: hashMethod,
		digest: new Uint8Array(data)
	};
	signedData = await cackeySignMessage(signRequest);
	signedData = Array.from(new Uint8Array(signedData));

	/*
	 * Encode signature
	 */
	switch (hashMethod) {
		case "SHA1":
			signedDataHeader = cackeySSHAgentEncodeString("ssh-rsa");
			break;
		case "SHA256":
			signedDataHeader = cackeySSHAgentEncodeString("rsa-sha2-256");
			break;
		case "SHA512":
			signedDataHeader = cackeySSHAgentEncodeString("rsa-sha2-512");
			break;
		default:
			signedDataHeader = [];
			break;
	}
	signedData = signedDataHeader.concat(cackeySSHAgentEncodeLV(signedData));

	/*
	 * Encode response
	 */
	response = [];








>















>
>
|
|
|
|
|
|
|
|
|
|
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















<
<
<
<
<
<
<
<
<
<
<
<
<
<







278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354














355
356
357
358
359
360
361
	certs.forEach(function(cert) {
		var key;

		key = cackeySSHAgentEncodeCertToKeyAndID(cert.certificate);

		if (key.key.join() == keyInfo.join()) {
			certToUse = cert;
			certToUseType = key.type;
		}
	});

	/*
	 * If no certificate is found, return an error
	 */
	if (!certToUse) {
		console.info("[cackeySSH] Unable to find a certificate to match the requested key:", keyInfo);

		return(null);
	}

	/*
	 * Perform hashing of the data as specified by the flags
	 */
	switch (certToUseType) {
		case "RSA":
			if ((flags & flagMeaning.SSH_AGENT_RSA_SHA2_512) == flagMeaning.SSH_AGENT_RSA_SHA2_512) {
				hashMethod = "SHA512";
				data = await crypto.subtle.digest("SHA-512", new Uint8Array(data));
			} else if ((flags & flagMeaning.SSH_AGENT_RSA_SHA2_256) == flagMeaning.SSH_AGENT_RSA_SHA2_256) {
				hashMethod = "SHA256";
				data = await crypto.subtle.digest("SHA-256", new Uint8Array(data));
			} else if (flags == 0) {
				hashMethod = "SHA1";
				data = await crypto.subtle.digest("SHA-1", new Uint8Array(data));
			} else {
				console.info("[cackeySSH] Sign request with flags set to", flags, "which is unsupported, failing the request.");

				return(null);
			}

			switch (hashMethod) {
				case "SHA1":
					signedDataHeader = cackeySSHAgentEncodeString("ssh-rsa");
					break;
				case "SHA256":
					signedDataHeader = cackeySSHAgentEncodeString("rsa-sha2-256");
					break;
				case "SHA512":
					signedDataHeader = cackeySSHAgentEncodeString("rsa-sha2-512");
					break;
				default:
					console.info("[cackeySSH] Unsupported hashing method for RSA:", hashMethod, "failing the request.");

					return(null);
					break;
			}
			break;
		default:
			console.info("[cackeySSH] Unsupported public key type:", certToUseType, "failing the request.");

			return(null);
			break;
	}

	/*
	 * Sign the data
	 */
	signRequest = {
		hash: hashMethod,
		digest: new Uint8Array(data)
	};
	signedData = await cackeySignMessage(signRequest);
	signedData = Array.from(new Uint8Array(signedData));

	/*
	 * Encode signature
	 */














	signedData = signedDataHeader.concat(cackeySSHAgentEncodeLV(signedData));

	/*
	 * Encode response
	 */
	response = [];

413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
		return;
	}

	/*
	 * Only accept connections from approved apps
	 */
	if (!socket.sender || !socket.sender.id || !cackeySSHAgentApprovedApps.includes(socket.sender.id)) {
		console.log("[cackeySSH] Disconnecting unapproved app: ", socket.sender);

		socket.disconnect();

		return;
	}

	console.log("[cackeySSH] Accepted connection from: ", socket.sender.id);
	socket.onMessage.addListener(function(request) {
		cackeySSHAgentHandleMessage(socket, request);







|
<
<







428
429
430
431
432
433
434
435


436
437
438
439
440
441
442
		return;
	}

	/*
	 * Only accept connections from approved apps
	 */
	if (!socket.sender || !socket.sender.id || !cackeySSHAgentApprovedApps.includes(socket.sender.id)) {
		console.log("[cackeySSH] Ignoring unapproved app: ", socket.sender);



		return;
	}

	console.log("[cackeySSH] Accepted connection from: ", socket.sender.id);
	socket.onMessage.addListener(function(request) {
		cackeySSHAgentHandleMessage(socket, request);