Home | History | Annotate | Line # | Download | only in tls
      1 /*
      2  * PKCS #8 (Private-key information syntax)
      3  * Copyright (c) 2006-2009, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "asn1.h"
     13 #include "bignum.h"
     14 #include "rsa.h"
     15 #include "pkcs5.h"
     16 #include "pkcs8.h"
     17 
     18 
     19 struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len)
     20 {
     21 	struct asn1_hdr hdr;
     22 	const u8 *pos, *end;
     23 	struct bignum *zero;
     24 	struct asn1_oid oid;
     25 	char obuf[80];
     26 
     27 	/* PKCS #8, Chapter 6 */
     28 
     29 	/* PrivateKeyInfo ::= SEQUENCE */
     30 	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
     31 		asn1_unexpected(&hdr,
     32 				"PKCS #8: Does not start with PKCS #8 header (SEQUENCE)");
     33 		return NULL;
     34 	}
     35 	pos = hdr.payload;
     36 	end = pos + hdr.length;
     37 
     38 	/* version Version (Version ::= INTEGER) */
     39 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
     40 		asn1_unexpected(&hdr, "PKCS #8: Expected INTEGER");
     41 		return NULL;
     42 	}
     43 
     44 	zero = bignum_init();
     45 	if (zero == NULL)
     46 		return NULL;
     47 
     48 	if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
     49 		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
     50 		bignum_deinit(zero);
     51 		return NULL;
     52 	}
     53 	pos = hdr.payload + hdr.length;
     54 
     55 	if (bignum_cmp_d(zero, 0) != 0) {
     56 		wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
     57 			   "beginning of private key; not found; assume "
     58 			   "PKCS #8 not used");
     59 		bignum_deinit(zero);
     60 		return NULL;
     61 	}
     62 	bignum_deinit(zero);
     63 
     64 	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
     65 	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
     66 	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
     67 		asn1_unexpected(&hdr,
     68 				"PKCS #8: Expected SEQUENCE (AlgorithmIdentifier); assume PKCS #8 not used");
     69 		return NULL;
     70 	}
     71 
     72 	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
     73 		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
     74 			   "(algorithm); assume PKCS #8 not used");
     75 		return NULL;
     76 	}
     77 
     78 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
     79 	wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
     80 
     81 	if (oid.len != 7 ||
     82 	    oid.oid[0] != 1 /* iso */ ||
     83 	    oid.oid[1] != 2 /* member-body */ ||
     84 	    oid.oid[2] != 840 /* us */ ||
     85 	    oid.oid[3] != 113549 /* rsadsi */ ||
     86 	    oid.oid[4] != 1 /* pkcs */ ||
     87 	    oid.oid[5] != 1 /* pkcs-1 */ ||
     88 	    oid.oid[6] != 1 /* rsaEncryption */) {
     89 		wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
     90 			   "algorithm %s", obuf);
     91 		return NULL;
     92 	}
     93 
     94 	pos = hdr.payload + hdr.length;
     95 
     96 	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
     97 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
     98 	    !asn1_is_octetstring(&hdr)) {
     99 		asn1_unexpected(&hdr,
    100 				"PKCS #8: Expected OCTETSTRING (privateKey)");
    101 		return NULL;
    102 	}
    103 	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
    104 
    105 	return (struct crypto_private_key *)
    106 		crypto_rsa_import_private_key(hdr.payload, hdr.length);
    107 }
    108 
    109 
    110 struct crypto_private_key *
    111 pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd)
    112 {
    113 	struct asn1_hdr hdr;
    114 	const u8 *pos, *end, *enc_alg;
    115 	size_t enc_alg_len;
    116 	u8 *data;
    117 	size_t data_len;
    118 
    119 	if (passwd == NULL)
    120 		return NULL;
    121 
    122 	/*
    123 	 * PKCS #8, Chapter 7
    124 	 * EncryptedPrivateKeyInfo ::= SEQUENCE {
    125 	 *   encryptionAlgorithm EncryptionAlgorithmIdentifier,
    126 	 *   encryptedData EncryptedData }
    127 	 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
    128 	 * EncryptedData ::= OCTET STRING
    129 	 */
    130 
    131 	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
    132 		asn1_unexpected(&hdr,
    133 				"PKCS #8: Does not start with PKCS #8 header (SEQUENCE); assume encrypted PKCS #8 not used");
    134 		return NULL;
    135 	}
    136 	pos = hdr.payload;
    137 	end = pos + hdr.length;
    138 
    139 	/* encryptionAlgorithm EncryptionAlgorithmIdentifier */
    140 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
    141 	    !asn1_is_sequence(&hdr)) {
    142 		asn1_unexpected(&hdr,
    143 				"PKCS #8: Expected SEQUENCE (AlgorithmIdentifier); assume encrypted PKCS #8 not used");
    144 		return NULL;
    145 	}
    146 	enc_alg = hdr.payload;
    147 	enc_alg_len = hdr.length;
    148 	pos = hdr.payload + hdr.length;
    149 
    150 	/* encryptedData EncryptedData */
    151 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
    152 	    !asn1_is_octetstring(&hdr)) {
    153 		asn1_unexpected(&hdr,
    154 				"PKCS #8: Expected OCTETSTRING (encryptedData)");
    155 		return NULL;
    156 	}
    157 
    158 	data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
    159 			     passwd, &data_len);
    160 	if (data) {
    161 		struct crypto_private_key *key;
    162 		key = pkcs8_key_import(data, data_len);
    163 		os_free(data);
    164 		return key;
    165 	}
    166 
    167 	return NULL;
    168 }
    169