$search
00001 /* 00002 * PKCS #8 (Private-key information syntax) 00003 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "asn1.h" 00019 #include "bignum.h" 00020 #include "rsa.h" 00021 #include "pkcs5.h" 00022 #include "pkcs8.h" 00023 00024 00025 struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len) 00026 { 00027 struct asn1_hdr hdr; 00028 const u8 *pos, *end; 00029 struct bignum *zero; 00030 struct asn1_oid oid; 00031 char obuf[80]; 00032 00033 /* PKCS #8, Chapter 6 */ 00034 00035 /* PrivateKeyInfo ::= SEQUENCE */ 00036 if (asn1_get_next(buf, len, &hdr) < 0 || 00037 hdr.class != ASN1_CLASS_UNIVERSAL || 00038 hdr.tag != ASN1_TAG_SEQUENCE) { 00039 wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " 00040 "header (SEQUENCE); assume PKCS #8 not used"); 00041 return NULL; 00042 } 00043 pos = hdr.payload; 00044 end = pos + hdr.length; 00045 00046 /* version Version (Version ::= INTEGER) */ 00047 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 00048 hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 00049 wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " 00050 "class %d tag 0x%x; assume PKCS #8 not used", 00051 hdr.class, hdr.tag); 00052 return NULL; 00053 } 00054 00055 zero = bignum_init(); 00056 if (zero == NULL) 00057 return NULL; 00058 00059 if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { 00060 wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); 00061 bignum_deinit(zero); 00062 return NULL; 00063 } 00064 pos = hdr.payload + hdr.length; 00065 00066 if (bignum_cmp_d(zero, 0) != 0) { 00067 wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " 00068 "beginning of private key; not found; assume " 00069 "PKCS #8 not used"); 00070 bignum_deinit(zero); 00071 return NULL; 00072 } 00073 bignum_deinit(zero); 00074 00075 /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier 00076 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ 00077 if (asn1_get_next(pos, len, &hdr) < 0 || 00078 hdr.class != ASN1_CLASS_UNIVERSAL || 00079 hdr.tag != ASN1_TAG_SEQUENCE) { 00080 wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " 00081 "(AlgorithmIdentifier) - found class %d tag 0x%x; " 00082 "assume PKCS #8 not used", 00083 hdr.class, hdr.tag); 00084 return NULL; 00085 } 00086 00087 if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { 00088 wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " 00089 "(algorithm); assume PKCS #8 not used"); 00090 return NULL; 00091 } 00092 00093 asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 00094 wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); 00095 00096 if (oid.len != 7 || 00097 oid.oid[0] != 1 /* iso */ || 00098 oid.oid[1] != 2 /* member-body */ || 00099 oid.oid[2] != 840 /* us */ || 00100 oid.oid[3] != 113549 /* rsadsi */ || 00101 oid.oid[4] != 1 /* pkcs */ || 00102 oid.oid[5] != 1 /* pkcs-1 */ || 00103 oid.oid[6] != 1 /* rsaEncryption */) { 00104 wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " 00105 "algorithm %s", obuf); 00106 return NULL; 00107 } 00108 00109 pos = hdr.payload + hdr.length; 00110 00111 /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ 00112 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 00113 hdr.class != ASN1_CLASS_UNIVERSAL || 00114 hdr.tag != ASN1_TAG_OCTETSTRING) { 00115 wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " 00116 "(privateKey) - found class %d tag 0x%x", 00117 hdr.class, hdr.tag); 00118 return NULL; 00119 } 00120 wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); 00121 00122 return (struct crypto_private_key *) 00123 crypto_rsa_import_private_key(hdr.payload, hdr.length); 00124 } 00125 00126 00127 struct crypto_private_key * 00128 pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd) 00129 { 00130 struct asn1_hdr hdr; 00131 const u8 *pos, *end, *enc_alg; 00132 size_t enc_alg_len; 00133 u8 *data; 00134 size_t data_len; 00135 00136 if (passwd == NULL) 00137 return NULL; 00138 00139 /* 00140 * PKCS #8, Chapter 7 00141 * EncryptedPrivateKeyInfo ::= SEQUENCE { 00142 * encryptionAlgorithm EncryptionAlgorithmIdentifier, 00143 * encryptedData EncryptedData } 00144 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 00145 * EncryptedData ::= OCTET STRING 00146 */ 00147 00148 if (asn1_get_next(buf, len, &hdr) < 0 || 00149 hdr.class != ASN1_CLASS_UNIVERSAL || 00150 hdr.tag != ASN1_TAG_SEQUENCE) { 00151 wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " 00152 "header (SEQUENCE); assume encrypted PKCS #8 not " 00153 "used"); 00154 return NULL; 00155 } 00156 pos = hdr.payload; 00157 end = pos + hdr.length; 00158 00159 /* encryptionAlgorithm EncryptionAlgorithmIdentifier */ 00160 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 00161 hdr.class != ASN1_CLASS_UNIVERSAL || 00162 hdr.tag != ASN1_TAG_SEQUENCE) { 00163 wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " 00164 "(AlgorithmIdentifier) - found class %d tag 0x%x; " 00165 "assume encrypted PKCS #8 not used", 00166 hdr.class, hdr.tag); 00167 return NULL; 00168 } 00169 enc_alg = hdr.payload; 00170 enc_alg_len = hdr.length; 00171 pos = hdr.payload + hdr.length; 00172 00173 /* encryptedData EncryptedData */ 00174 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 00175 hdr.class != ASN1_CLASS_UNIVERSAL || 00176 hdr.tag != ASN1_TAG_OCTETSTRING) { 00177 wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " 00178 "(encryptedData) - found class %d tag 0x%x", 00179 hdr.class, hdr.tag); 00180 return NULL; 00181 } 00182 00183 data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, 00184 passwd, &data_len); 00185 if (data) { 00186 struct crypto_private_key *key; 00187 key = pkcs8_key_import(data, data_len); 00188 os_free(data); 00189 return key; 00190 } 00191 00192 return NULL; 00193 }