Internal TLS: Added support for parsing PKCS #8 formatted private keys

The internal TLS implementation can now use both PKCS #1 RSA private key
and PKCS #8 encapsulated RSA private key. PKCS #8 encrypted private key is
not yet supported.
This commit is contained in:
Jouni Malinen 2008-06-02 19:39:46 +03:00
parent b5aebee49e
commit d952d16df4
2 changed files with 117 additions and 0 deletions

View file

@ -22,6 +22,7 @@
#include "aes.h" #include "aes.h"
#include "tls/rsa.h" #include "tls/rsa.h"
#include "tls/bignum.h" #include "tls/bignum.h"
#include "tls/asn1.h"
#ifdef EAP_TLS_FUNCS #ifdef EAP_TLS_FUNCS
@ -434,9 +435,122 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
} }
static struct crypto_private_key *
crypto_pkcs8_key_import(const u8 *buf, size_t len)
{
struct asn1_hdr hdr;
const u8 *pos, *end;
struct bignum *zero;
struct asn1_oid oid;
char obuf[80];
/* PKCS #8, Chapter 6 */
/* PrivateKeyInfo ::= SEQUENCE */
if (asn1_get_next(buf, len, &hdr) < 0 ||
hdr.class != ASN1_CLASS_UNIVERSAL ||
hdr.tag != ASN1_TAG_SEQUENCE) {
wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
"header (SEQUENCE); assume PKCS #8 not used");
return NULL;
}
pos = hdr.payload;
end = pos + hdr.length;
/* version Version (Version ::= INTEGER) */
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
"class %d tag 0x%x; assume PKCS #8 not used",
hdr.class, hdr.tag);
return NULL;
}
zero = bignum_init();
if (zero == NULL)
return NULL;
if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
bignum_deinit(zero);
return NULL;
}
pos = hdr.payload + hdr.length;
if (bignum_cmp_d(zero, 0) != 0) {
wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
"beginning of private key; not found; assume "
"PKCS #8 not used");
bignum_deinit(zero);
return NULL;
}
bignum_deinit(zero);
/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
* (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
if (asn1_get_next(pos, len, &hdr) < 0 ||
hdr.class != ASN1_CLASS_UNIVERSAL ||
hdr.tag != ASN1_TAG_SEQUENCE) {
wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
"(AlgorithmIdentifier) - found class %d tag 0x%x; "
"assume PKCS #8 not used",
hdr.class, hdr.tag);
return NULL;
}
if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
"(algorithm); assume PKCS #8 not used");
return NULL;
}
asn1_oid_to_str(&oid, obuf, sizeof(obuf));
wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
if (oid.len != 7 ||
oid.oid[0] != 1 /* iso */ ||
oid.oid[1] != 2 /* member-body */ ||
oid.oid[2] != 840 /* us */ ||
oid.oid[3] != 113549 /* rsadsi */ ||
oid.oid[4] != 1 /* pkcs */ ||
oid.oid[5] != 1 /* pkcs-1 */ ||
oid.oid[6] != 1 /* rsaEncryption */) {
wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
"algorithm %s", obuf);
return NULL;
}
pos = hdr.payload + hdr.length;
/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
hdr.class != ASN1_CLASS_UNIVERSAL ||
hdr.tag != ASN1_TAG_OCTETSTRING) {
wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
"(privateKey) - found class %d tag 0x%x",
hdr.class, hdr.tag);
return NULL;
}
wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
return (struct crypto_private_key *)
crypto_rsa_import_private_key(hdr.payload, hdr.length);
}
struct crypto_private_key * crypto_private_key_import(const u8 *key, struct crypto_private_key * crypto_private_key_import(const u8 *key,
size_t len) size_t len)
{ {
struct crypto_private_key *res;
/* First, check for possible PKCS #8 encoding */
res = crypto_pkcs8_key_import(key, len);
if (res)
return res;
/* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
"key");
return (struct crypto_private_key *) return (struct crypto_private_key *)
crypto_rsa_import_private_key(key, len); crypto_rsa_import_private_key(key, len);
} }

View file

@ -8,6 +8,9 @@ ChangeLog for wpa_supplicant
* fixed the OpenSSL patches (0.9.8g and 0.9.9) for EAP-FAST to * fixed the OpenSSL patches (0.9.8g and 0.9.9) for EAP-FAST to
allow fallback to full handshake if server rejects PAC-Opaque allow fallback to full handshake if server rejects PAC-Opaque
* added fragmentation support for EAP-TNC * added fragmentation support for EAP-TNC
* added support for parsing PKCS #8 formatted private keys into the
internal TLS implementation (both PKCS #1 RSA key and PKCS #8
encapsulated RSA key can now be used)
2008-02-22 - v0.6.3 2008-02-22 - v0.6.3
* removed 'nai' and 'eappsk' network configuration variables that were * removed 'nai' and 'eappsk' network configuration variables that were