Check-in [648368d41d]
Overview
Comment:Added support for x509v3-ssh-rsa and x509v3-sign-rsa to agent
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:648368d41d22147a0a1d77ff4ceb6df70a6f81f7
User & Date: rkeene on 2019-01-31 15:04:33
Other Links: manifest | tags
Context
2019-02-04
17:32
More X.509v3 support for SSH agent check-in: 0defa19481 user: rkeene tags: trunk
2019-01-31
15:04
Added support for x509v3-ssh-rsa and x509v3-sign-rsa to agent check-in: 648368d41d user: rkeene tags: trunk
13:29
Ensure externally connectable IDs are present check-in: e04736eb53 user: rkeene tags: trunk
Changes

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

     2      2    * CACKey SSH Agent for ChromeOS
     3      3    */
     4      4   
     5      5   cackeySSHAgentApprovedApps = [
     6      6   	"pnhechapfaindjhompbnflcldabbghjo",
     7      7   	"okddffdblfhhnmhodogpojmfkjmhinfp"
     8      8   ];
            9  +
           10  +/*
           11  + * XXX:TODO: Expose UI for this
           12  + */
           13  +cackeySSHAgentFeatures = {
           14  +	enabled: true,
           15  +	includeKeys: true,
           16  +	includeCerts: true,
           17  +	legacy: false
           18  +};
           19  +
           20  +/*
           21  + * Feature support checking
           22  + */
           23  +function cackeySSHAgentGetSSHKeyTypes() {
           24  +	var types = [];
           25  +
           26  +	if (cackeySSHAgentFeatures.includeKeys) {
           27  +		types.push("ssh");
           28  +	}
           29  +
           30  +	if (cackeySSHAgentFeatures.includeCerts) {
           31  +		types.push("x509v3-ssh");
           32  +
           33  +		if (cackeySSHAgentFeatures.legacy) {
           34  +			types.push("x509v3-sign");
           35  +		}
           36  +	}
           37  +
           38  +	return(types);
           39  +}
           40  +
           41  +async function cackeySSHAgentGetCertificates() {
           42  +	var certs;
           43  +
           44  +	if (!cackeySSHAgentFeatures.enabled) {
           45  +		return([]);
           46  +	}
           47  +
           48  +	certs = await cackeyListCertificates();
           49  +
           50  +	return(certs);
           51  +}
     9     52   
    10     53   /*
    11     54    * SSH Element Encoding/Decoding
    12     55    */
    13     56   function cackeySSHAgentEncodeInt(uint32) {
    14     57   	var result;
    15     58   
................................................................................
    46     89   			while (bigInt) {
    47     90   				result.push(bigInt & 0xff);
    48     91   				bigInt = bigInt >> 8;
    49     92   			}
    50     93   			result.reverse();
    51     94   			break;
    52     95   		case "object":
    53         -			result = [];
    54         -			new Uint8Array(bigInt.toByteArray()).forEach(function(e) {
    55         -				result.push(e);
    56         -			});
           96  +			result = Array.from(new Uint8Array(bigInt.toByteArray()));
    57     97   			break;
    58     98   	}
    59     99   
    60    100   	result = cackeySSHAgentEncodeLV(result);
    61    101   
    62    102   	return(result);
    63    103   }
................................................................................
    84    124   	result = input.slice(0, info.value);
    85    125   
    86    126   	return({
    87    127   		value: result,
    88    128   		output: input.slice(info.value)
    89    129   	});
    90    130   }
          131  +
          132  +function cackeySSHAgentEncodeArray(input) {
          133  +	var result;
          134  +
          135  +	result = cackeySSHAgentEncodeInt(input.length);
          136  +	input.forEach(function(element) {
          137  +		result = result.concat(element);
          138  +	});
          139  +
          140  +	return(result);
          141  +}
    91    142   
    92    143   function cackeySSHAgentEncodeToUTF8Array(str) {
    93    144   	var utf8 = [];
    94    145   
    95    146   	if (typeof(str) === "string") {
    96    147   		str = str.split("").map(function(c) {
    97    148   			return(c.charCodeAt(0));
................................................................................
   154    205   			buffer = buffer.join("");
   155    206   			break;
   156    207   	}
   157    208   
   158    209   	return(buffer);
   159    210   }
   160    211   
   161         -function cackeySSHAgentEncodeCertToKeyAndID(cert) {
          212  +function cackeySSHAgentEncodeCertToKeyAndID(cert, keyType) {
   162    213   	var result = null, resultKey = null;
   163         -	var certObj;
          214  +	var certObj, certBytes;
   164    215   	var publicKey;
   165    216   
   166    217   	certObj = new X509;
   167    218   	if (!certObj) {
   168    219   		return(result);
   169    220   	}
   170    221   
   171         -	certObj.readCertHex(cackeySSHAgentEncodeBinaryToHex(cert));
          222  +	certBytes = Array.from(new Uint8Array(cert));
          223  +
          224  +	certObj.readCertHex(cackeySSHAgentEncodeBinaryToHex(certBytes));
   172    225   
   173    226   	publicKey = certObj.getPublicKey();
   174    227   
   175         -	switch (publicKey.type) {
   176         -		case "RSA":
   177         -			resultKey = cackeySSHAgentEncodeString("ssh-rsa");
   178         -			resultKey = resultKey.concat(cackeySSHAgentEncodeBigInt(publicKey.e));
   179         -			resultKey = resultKey.concat(cackeySSHAgentEncodeBigInt(publicKey.n));
          228  +	switch (keyType) {
          229  +		case "ssh":
          230  +			switch (publicKey.type) {
          231  +				case "RSA":
          232  +					resultKey = cackeySSHAgentEncodeString("ssh-rsa");
          233  +					resultKey = resultKey.concat(cackeySSHAgentEncodeBigInt(publicKey.e));
          234  +					resultKey = resultKey.concat(cackeySSHAgentEncodeBigInt(publicKey.n));
          235  +					break;
          236  +				default:
          237  +					console.log("[cackeySSH] Unsupported public key type:", keyType, "/", publicKey.type, "-- ignoring.");
          238  +					break;
          239  +			}
          240  +			break;
          241  +		case "x509v3-sign":
          242  +			resultKey = certBytes;
          243  +			break;
          244  +		case "x509v3-ssh":
          245  +			switch (publicKey.type) {
          246  +				case "RSA":
          247  +					resultKey = cackeySSHAgentEncodeString("x509v3-ssh-rsa");
          248  +
          249  +					/*
          250  +					 * Array of certificates
          251  +					 */
          252  +					resultKey = resultKey.concat(cackeySSHAgentEncodeArray([
          253  +						cackeySSHAgentEncodeLV(certBytes)
          254  +					]));
          255  +
          256  +					/*
          257  +					 * Array of OCSP responses
          258  +					 */
          259  +					resultKey = resultKey.concat(cackeySSHAgentEncodeArray([]));
          260  +					break;
          261  +				default:
          262  +					console.log("[cackeySSH] Unsupported public key type:", keyType, "/", publicKey.type, "-- ignoring.");
          263  +					break;
          264  +			}
   180    265   			break;
   181    266   		default:
   182         -			console.log("[cackeySSH] Unsupported public key type:", publicKey.type, "-- ignoring.");
          267  +			console.log("[cackeySSH] Unsupported SSH key type:", keyType, "-- ignoring.");
          268  +			break;
   183    269   	}
   184    270   
   185    271   	if (resultKey) {
   186    272   		result = {
   187    273   			id: certObj.getSubjectString(),
   188         -			type: publicKey.type,
          274  +			publicKeyType: publicKey.type,
          275  +			sshKeyType: keyType,
   189    276   			key: resultKey
   190    277   		};
   191    278   	}
   192    279   
   193    280   	return(result);
   194    281   }
   195    282   
................................................................................
   200    287   	var response;
   201    288   	var certs = [];
   202    289   	var keys = [];
   203    290   
   204    291   	/*
   205    292   	 * Get a list of certificates
   206    293   	 */
   207         -	certs = await cackeyListCertificates();
          294  +	certs = await cackeySSHAgentGetCertificates();
   208    295   
   209    296   	/*
   210    297   	 * Convert each certificate to an SSH key blob
   211    298   	 */
   212         -	certs.forEach(function(cert) {
   213         -		var key;
          299  +	cackeySSHAgentGetSSHKeyTypes().forEach(function(sshKeyType) {
          300  +		certs.forEach(function(cert) {
          301  +			var key;
   214    302   
   215         -		key = cackeySSHAgentEncodeCertToKeyAndID(cert.certificate);
          303  +			key = cackeySSHAgentEncodeCertToKeyAndID(cert.certificate, sshKeyType);
   216    304   
   217         -		if (key) {
   218         -			keys.push(key);
   219         -		}
          305  +			if (key) {
          306  +				keys.push(key);
          307  +			}
          308  +		});
   220    309   	});
   221    310   
   222    311   	/*
   223    312   	 * Encode response
   224    313   	 */
   225    314   	response = [];
   226    315   
................................................................................
   269    358   	flags = cackeySSHAgentDecodeInt(request);
   270    359   	request = flags.output;
   271    360   	flags = flags.value;
   272    361   
   273    362   	/*
   274    363   	 * Find the certificate that matches the requested key
   275    364   	 */
   276         -	certs = await cackeyListCertificates();
          365  +	certs = await cackeySSHAgentGetCertificates();
   277    366   	certToUse = null;
   278         -	certs.forEach(function(cert) {
   279         -		var key;
          367  +	cackeySSHAgentGetSSHKeyTypes().forEach(function(sshKeyType) {
          368  +		certs.forEach(function(cert) {
          369  +			var key;
   280    370   
   281         -		key = cackeySSHAgentEncodeCertToKeyAndID(cert.certificate);
          371  +			key = cackeySSHAgentEncodeCertToKeyAndID(cert.certificate, sshKeyType);
   282    372   
   283         -		if (key.key.join() == keyInfo.join()) {
   284         -			certToUse = cert;
   285         -			certToUseType = key.type;
   286         -		}
          373  +			if (key.key.join() == keyInfo.join()) {
          374  +				certToUse = cert;
          375  +				certToUseType = key.publicKeyType;
          376  +			}
          377  +		});
   287    378   	});
   288    379   
   289    380   	/*
   290    381   	 * If no certificate is found, return an error
   291    382   	 */
   292    383   	if (!certToUse) {
   293    384   		console.info("[cackeySSH] Unable to find a certificate to match the requested key:", keyInfo);