Home | History | Annotate | 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 ||
     31 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
     32 	    hdr.tag != ASN1_TAG_SEQUENCE) {
     33 		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
     34 			   "header (SEQUENCE); assume PKCS #8 not used");
     35 		return NULL;
     36 	}
     37 	pos = hdr.payload;
     38 	end = pos + hdr.length;
     39 
     40 	/* version Version (Version ::= INTEGER) */
     41 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
     42 	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
     43 		wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
     44 			   "class %d tag 0x%x; assume PKCS #8 not used",
     45 			   hdr.class, hdr.tag);
     46 		return NULL;
     47 	}
     48 
     49 	zero = bignum_init();
     50 	if (zero == NULL)
     51 		return NULL;
     52 
     53 	if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
     54 		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
     55 		bignum_deinit(zero);
     56 		return NULL;
     57 	}
     58 	pos = hdr.payload + hdr.length;
     59 
     60 	if (bignum_cmp_d(zero, 0) != 0) {
     61 		wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
     62 			   "beginning of private key; not found; assume "
     63 			   "PKCS #8 not used");
     64 		bignum_deinit(zero);
     65 		return NULL;
     66 	}
     67 	bignum_deinit(zero);
     68 
     69 	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
     70 	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
     71 	if (asn1_get_next(pos, len, &hdr) < 0 ||
     72 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
     73 	    hdr.tag != ASN1_TAG_SEQUENCE) {
     74 		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
     75 			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
     76 			   "assume PKCS #8 not used",
     77 			   hdr.class, hdr.tag);
     78 		return NULL;
     79 	}
     80 
     81 	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
     82 		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
     83 			   "(algorithm); assume PKCS #8 not used");
     84 		return NULL;
     85 	}
     86 
     87 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
     88 	wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
     89 
     90 	if (oid.len != 7 ||
     91 	    oid.oid[0] != 1 /* iso */ ||
     92 	    oid.oid[1] != 2 /* member-body */ ||
     93 	    oid.oid[2] != 840 /* us */ ||
     94 	    oid.oid[3] != 113549 /* rsadsi */ ||
     95 	    oid.oid[4] != 1 /* pkcs */ ||
     96 	    oid.oid[5] != 1 /* pkcs-1 */ ||
     97 	    oid.oid[6] != 1 /* rsaEncryption */) {
     98 		wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
     99 			   "algorithm %s", obuf);
    100 		return NULL;
    101 	}
    102 
    103 	pos = hdr.payload + hdr.length;
    104 
    105 	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
    106 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
    107 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
    108 	    hdr.tag != ASN1_TAG_OCTETSTRING) {
    109 		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
    110 			   "(privateKey) - found class %d tag 0x%x",
    111 			   hdr.class, hdr.tag);
    112 		return NULL;
    113 	}
    114 	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
    115 
    116 	return (struct crypto_private_key *)
    117 		crypto_rsa_import_private_key(hdr.payload, hdr.length);
    118 }
    119 
    120 
    121 struct crypto_private_key *
    122 pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd)
    123 {
    124 	struct asn1_hdr hdr;
    125 	const u8 *pos, *end, *enc_alg;
    126 	size_t enc_alg_len;
    127 	u8 *data;
    128 	size_t data_len;
    129 
    130 	if (passwd == NULL)
    131 		return NULL;
    132 
    133 	/*
    134 	 * PKCS #8, Chapter 7
    135 	 * EncryptedPrivateKeyInfo ::= SEQUENCE {
    136 	 *   encryptionAlgorithm EncryptionAlgorithmIdentifier,
    137 	 *   encryptedData EncryptedData }
    138 	 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
    139 	 * EncryptedData ::= OCTET STRING
    140 	 */
    141 
    142 	if (asn1_get_next(buf, len, &hdr) < 0 ||
    143 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
    144 	    hdr.tag != ASN1_TAG_SEQUENCE) {
    145 		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
    146 			   "header (SEQUENCE); assume encrypted PKCS #8 not "
    147 			   "used");
    148 		return NULL;
    149 	}
    150 	pos = hdr.payload;
    151 	end = pos + hdr.length;
    152 
    153 	/* encryptionAlgorithm EncryptionAlgorithmIdentifier */
    154 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
    155 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
    156 	    hdr.tag != ASN1_TAG_SEQUENCE) {
    157 		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
    158 			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
    159 			   "assume encrypted PKCS #8 not used",
    160 			   hdr.class, hdr.tag);
    161 		return NULL;
    162 	}
    163 	enc_alg = hdr.payload;
    164 	enc_alg_len = hdr.length;
    165 	pos = hdr.payload + hdr.length;
    166 
    167 	/* encryptedData EncryptedData */
    168 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
    169 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
    170 	    hdr.tag != ASN1_TAG_OCTETSTRING) {
    171 		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
    172 			   "(encryptedData) - found class %d tag 0x%x",
    173 			   hdr.class, hdr.tag);
    174 		return NULL;
    175 	}
    176 
    177 	data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
    178 			     passwd, &data_len);
    179 	if (data) {
    180 		struct crypto_private_key *key;
    181 		key = pkcs8_key_import(data, data_len);
    182 		os_free(data);
    183 		return key;
    184 	}
    185 
    186 	return NULL;
    187 }
    188