/* Tests loading a bad key in PKCS8 format */ static int test_EVP_PKCS82PKEY(void) { int ret = 0; const unsigned char *derp = kExampleBadECKeyDER; PKCS8_PRIV_KEY_INFO *p8inf = NULL; EVP_PKEY *pkey = NULL; p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER)); if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) { fprintf(stderr, "Failed to parse key\n"); goto done; } pkey = EVP_PKCS82PKEY(p8inf); if (pkey) { fprintf(stderr, "Imported invalid EC key\n"); goto done; } ret = 1; done: PKCS8_PRIV_KEY_INFO_free(p8inf); EVP_PKEY_free(pkey); return ret; }
static int openssl_import_keypair(const keymaster_device_t* dev, const uint8_t* key, const size_t key_length, uint8_t** key_blob, size_t* key_blob_length) { int response = -1; if (key == NULL) { ALOGW("input key == NULL"); return -1; } else if (key_blob == NULL || key_blob_length == NULL) { ALOGW("output key blob or length == NULL"); return -1; } Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length)); if (pkcs8.get() == NULL) { logOpenSSLError("openssl_import_keypair"); return -1; } /* assign to EVP */ Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get())); if (pkey.get() == NULL) { logOpenSSLError("openssl_import_keypair"); return -1; } OWNERSHIP_TRANSFERRED(pkcs8); if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), key_blob, key_blob_length)) { return -1; } return 0; }
TEST_F(KeymasterTest, ImportKeyPair_EC_Success) { uint8_t* key_blob; size_t key_blob_length; ASSERT_EQ(0, sDevice->import_keypair(sDevice, TEST_EC_KEY_1, sizeof(TEST_EC_KEY_1), &key_blob, &key_blob_length)) << "Should successfully import an EC key"; UniqueKey key(&sDevice, key_blob, key_blob_length); uint8_t* x509_data; size_t x509_data_length; ASSERT_EQ(0, sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, &x509_data, &x509_data_length)) << "Should be able to retrieve EC public key successfully"; UniqueBlob x509_blob(x509_data, x509_data_length); const unsigned char *tmp = static_cast<const unsigned char*>(x509_blob.get()); Unique_EVP_PKEY actual(d2i_PUBKEY((EVP_PKEY**) NULL, &tmp, static_cast<long>(x509_blob.length()))); ASSERT_EQ(EVP_PKEY_type(actual.get()->type), EVP_PKEY_EC) << "Generated key type should be of type EC"; const unsigned char *expectedTmp = static_cast<const unsigned char*>(TEST_EC_KEY_1); Unique_PKCS8_PRIV_KEY_INFO expectedPkcs8( d2i_PKCS8_PRIV_KEY_INFO((PKCS8_PRIV_KEY_INFO**) NULL, &expectedTmp, sizeof(TEST_EC_KEY_1))); Unique_EVP_PKEY expected(EVP_PKCS82PKEY(expectedPkcs8.get())); ASSERT_EQ(1, EVP_PKEY_cmp(expected.get(), actual.get())) << "Expected and actual keys should match"; }
/* Tests loading a bad key in PKCS8 format */ static int test_EVP_PKCS82PKEY(void) { int ret = 0; const unsigned char *derp = kExampleBadECKeyDER; PKCS8_PRIV_KEY_INFO *p8inf = NULL; EVP_PKEY *pkey = NULL; if (!TEST_ptr(p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER)))) goto done; if (!TEST_ptr_eq(derp, kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER))) goto done; if (!TEST_ptr_null(pkey = EVP_PKCS82PKEY(p8inf))) goto done; ret = 1; done: PKCS8_PRIV_KEY_INFO_free(p8inf); EVP_PKEY_free(pkey); return ret; }
__attribute__((visibility("default"))) int openssl_import_keypair(const keymaster0_device_t*, const uint8_t* key, const size_t key_length, uint8_t** key_blob, size_t* key_blob_length) { if (key == NULL) { ALOGW("input key == NULL"); return -1; } else if (key_blob == NULL || key_blob_length == NULL) { ALOGW("output key blob or length == NULL"); return -1; } Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length)); if (pkcs8.get() == NULL) { logOpenSSLError("openssl_import_keypair"); return -1; } /* assign to EVP */ Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get())); if (pkey.get() == NULL) { logOpenSSLError("openssl_import_keypair"); return -1; } if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), key_blob, key_blob_length)) { return -1; } return 0; }
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp, long len) { EVP_PKEY *ret; if (out == NULL || *out == NULL) { ret = EVP_PKEY_new(); if (ret == NULL) { OPENSSL_PUT_ERROR(EVP, ERR_R_EVP_LIB); return NULL; } } else { ret = *out; } if (!EVP_PKEY_set_type(ret, type)) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; } const uint8_t *in = *inp; if (!ret->ameth->old_priv_decode || !ret->ameth->old_priv_decode(ret, &in, len)) { if (ret->ameth->priv_decode) { /* Reset |in| in case |old_priv_decode| advanced it on error. */ in = *inp; PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &in, len); if (!p8) { goto err; } EVP_PKEY_free(ret); ret = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (ret == NULL) { goto err; } } else { OPENSSL_PUT_ERROR(EVP, ERR_R_ASN1_LIB); goto err; } } if (out != NULL) { *out = ret; } *inp = in; return ret; err: if (out == NULL || *out != ret) { EVP_PKEY_free(ret); } return NULL; }
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, long length) { STACK_OF(ASN1_TYPE) *inkey; const unsigned char *p; int keytype; p = *pp; /* * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by * analyzing it we can determine the passed structure: this assumes the * input is surrounded by an ASN1 SEQUENCE. */ inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length); p = *pp; /* * Since we only need to discern "traditional format" RSA and DSA keys we * can just count the elements. */ if (sk_ASN1_TYPE_num(inkey) == 6) keytype = EVP_PKEY_DSA; else if (sk_ASN1_TYPE_num(inkey) == 4) keytype = EVP_PKEY_EC; else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not * traditional format */ PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); EVP_PKEY *ret; sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); if (!p8) { ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); return NULL; } ret = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (ret == NULL) return NULL; *pp = p; if (a) { *a = ret; } return ret; } else keytype = EVP_PKEY_RSA; sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); return d2i_PrivateKey(keytype, a, pp, length); }
// Decode from PKCS#8 BER bool OSSLECPrivateKey::PKCS8Decode(const ByteString& ber) { int len = ber.size(); if (len <= 0) return false; const unsigned char* priv = ber.const_byte_str(); PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len); if (p8 == NULL) return false; EVP_PKEY* pkey = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (pkey == NULL) return false; EC_KEY* key = EVP_PKEY_get1_EC_KEY(pkey); EVP_PKEY_free(pkey); if (key == NULL) return false; setFromOSSL(key); EC_KEY_free(key); return true; }
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) { STACK_OF(ASN1_TYPE) *inkey; const uint8_t *p; int keytype; p = *inp; /* Dirty trick: read in the ASN1 data into out STACK_OF(ASN1_TYPE): * by analyzing it we can determine the passed structure: this * assumes the input is surrounded by an ASN1 SEQUENCE. */ inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, len); /* Since we only need to discern "traditional format" RSA and DSA * keys we can just count the elements. */ if (sk_ASN1_TYPE_num(inkey) == 6) { keytype = EVP_PKEY_DSA; } else if (sk_ASN1_TYPE_num(inkey) == 4) { keytype = EVP_PKEY_EC; } else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not traditional format */ p = *inp; PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); EVP_PKEY *ret; sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); if (!p8) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE); return NULL; } ret = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (ret == NULL) { return NULL; } *inp = p; if (out) { *out = ret; } return ret; } else { keytype = EVP_PKEY_RSA; } sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); return d2i_PrivateKey(keytype, out, inp, len); }
/* static */ Key* Key::ImportKey(const AuthorizationSet& key_description, keymaster_key_format_t key_format, const uint8_t* key_data, size_t key_data_length, const Logger& logger, keymaster_error_t* error) { *error = KM_ERROR_OK; if (key_data == NULL || key_data_length <= 0) { *error = KM_ERROR_INVALID_KEY_BLOB; return NULL; } if (key_format != KM_KEY_FORMAT_PKCS8) { *error = KM_ERROR_UNSUPPORTED_KEY_FORMAT; return NULL; } UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8( d2i_PKCS8_PRIV_KEY_INFO(NULL, &key_data, key_data_length)); if (pkcs8.get() == NULL) { *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; return NULL; } UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKCS82PKEY(pkcs8.get())); if (pkey.get() == NULL) { *error = KM_ERROR_INVALID_KEY_BLOB; return NULL; } UniquePtr<Key> key; switch (EVP_PKEY_type(pkey->type)) { case EVP_PKEY_RSA: return RsaKey::ImportKey(key_description, pkey.get(), logger, error); case EVP_PKEY_DSA: return DsaKey::ImportKey(key_description, pkey.get(), logger, error); case EVP_PKEY_EC: return EcdsaKey::ImportKey(key_description, pkey.get(), logger, error); default: *error = KM_ERROR_UNSUPPORTED_ALGORITHM; return NULL; } *error = KM_ERROR_UNIMPLEMENTED; return NULL; }
EVP_PKEY * PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) { char *nm = NULL; const unsigned char *p = NULL; unsigned char *data = NULL; long len; int slen; EVP_PKEY *ret = NULL; if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) return NULL; p = data; if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); if (!p8inf) goto p8err; ret = EVP_PKCS82PKEY(p8inf); if (x) { EVP_PKEY_free(*x); *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; X509_SIG *p8; int klen; char psbuf[PEM_BUFSIZE]; p8 = d2i_X509_SIG(NULL, &p, len); if (!p8) goto p8err; if (cb) klen = cb(psbuf, PEM_BUFSIZE, 0, u); else klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); if (klen <= 0) { PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ); X509_SIG_free(p8); goto err; } p8inf = PKCS8_decrypt(p8, psbuf, klen); X509_SIG_free(p8); if (!p8inf) goto p8err; ret = EVP_PKCS82PKEY(p8inf); if (x) { EVP_PKEY_free(*x); *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) { const EVP_PKEY_ASN1_METHOD *ameth; ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); if (!ameth || !ameth->old_priv_decode) goto p8err; ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len); } p8err: if (ret == NULL) PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB); err: free(nm); OPENSSL_cleanse(data, len); free(data); return (ret); }
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) { char *nm=NULL; const unsigned char *p=NULL; unsigned char *data=NULL; long len; EVP_PKEY *ret=NULL; if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) return NULL; p = data; if (strcmp(nm,PEM_STRING_RSA) == 0) ret=d2i_PrivateKey(EVP_PKEY_RSA,x,&p,len); else if (strcmp(nm,PEM_STRING_DSA) == 0) ret=d2i_PrivateKey(EVP_PKEY_DSA,x,&p,len); else if (strcmp(nm,PEM_STRING_ECPRIVATEKEY) == 0) ret=d2i_PrivateKey(EVP_PKEY_EC,x,&p,len); else if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); if(!p8inf) goto p8err; ret = EVP_PKCS82PKEY(p8inf); if(x) { if(*x) EVP_PKEY_free((EVP_PKEY *)*x); *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } else if (strcmp(nm,PEM_STRING_PKCS8) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; X509_SIG *p8; int klen; char psbuf[PEM_BUFSIZE]; p8 = d2i_X509_SIG(NULL, &p, len); if(!p8) goto p8err; if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u); else klen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u); if (klen <= 0) { PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ); X509_SIG_free(p8); goto err; } p8inf = PKCS8_decrypt(p8, psbuf, klen); X509_SIG_free(p8); if(!p8inf) goto p8err; ret = EVP_PKCS82PKEY(p8inf); if(x) { if(*x) EVP_PKEY_free((EVP_PKEY *)*x); *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } p8err: if (ret == NULL) PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY,ERR_R_ASN1_LIB); err: OPENSSL_free(nm); OPENSSL_cleanse(data, len); OPENSSL_free(data); return(ret); }
static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name, const char *pem_header, const unsigned char *blob, size_t len, void **pctx, int *matchcount, const UI_METHOD *ui_method, void *ui_data) { OSSL_STORE_INFO *store_info = NULL; EVP_PKEY *pkey = NULL; const EVP_PKEY_ASN1_METHOD *ameth = NULL; if (pem_name != NULL) { if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) { PKCS8_PRIV_KEY_INFO *p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, len); *matchcount = 1; if (p8inf != NULL) pkey = EVP_PKCS82PKEY(p8inf); PKCS8_PRIV_KEY_INFO_free(p8inf); } else { int slen; if ((slen = pem_check_suffix(pem_name, "PRIVATE KEY")) > 0 && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL) { *matchcount = 1; pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &blob, len); } } } else { int i; for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { EVP_PKEY *tmp_pkey = NULL; const unsigned char *tmp_blob = blob; ameth = EVP_PKEY_asn1_get0(i); if (ameth->pkey_flags & ASN1_PKEY_ALIAS) continue; tmp_pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &tmp_blob, len); if (tmp_pkey != NULL) { if (pkey != NULL) EVP_PKEY_free(tmp_pkey); else pkey = tmp_pkey; (*matchcount)++; } } if (*matchcount > 1) { EVP_PKEY_free(pkey); pkey = NULL; } } if (pkey == NULL) /* No match */ return NULL; store_info = OSSL_STORE_INFO_new_PKEY(pkey); if (store_info == NULL) EVP_PKEY_free(pkey); return store_info; }
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) { char *nm = NULL; const unsigned char *p = NULL; unsigned char *data = NULL; long len; EVP_PKEY *ret = NULL; if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) return NULL; p = data; if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); if (!p8inf) goto p8err; ret = EVP_PKCS82PKEY(p8inf); if (x) { if (*x) EVP_PKEY_free((EVP_PKEY *)*x); *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; X509_SIG *p8; int klen; char psbuf[PEM_BUFSIZE]; p8 = d2i_X509_SIG(NULL, &p, len); if (!p8) goto p8err; klen = 0; if (!cb) cb = PEM_def_callback; klen = cb(psbuf, PEM_BUFSIZE, 0, u); if (klen <= 0) { OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); X509_SIG_free(p8); goto err; } p8inf = PKCS8_decrypt(p8, psbuf, klen); X509_SIG_free(p8); OPENSSL_cleanse(psbuf, klen); if (!p8inf) goto p8err; ret = EVP_PKCS82PKEY(p8inf); if (x) { if (*x) EVP_PKEY_free((EVP_PKEY *)*x); *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } else if (strcmp(nm, PEM_STRING_RSA) == 0) { /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the * standalone format. This and the cases below probably should not * accept PKCS#8. */ ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); } else if (strcmp(nm, PEM_STRING_EC) == 0) { ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); } else if (strcmp(nm, PEM_STRING_DSA) == 0) { ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len); } p8err: if (ret == NULL) OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); err: OPENSSL_free(nm); OPENSSL_cleanse(data, len); OPENSSL_free(data); return (ret); }
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) { EVP_PKEY *ret; const unsigned char *p = *pp; if ((a == NULL) || (*a == NULL)) { if ((ret = EVP_PKEY_new()) == NULL) { ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB); return (NULL); } } else { ret = *a; #ifndef OPENSSL_NO_ENGINE if (ret->engine) { ENGINE_finish(ret->engine); ret->engine = NULL; } #endif } if (!EVP_PKEY_set_type(ret, type)) { ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; } if (!ret->ameth->old_priv_decode || !ret->ameth->old_priv_decode(ret, &p, length)) { if (ret->ameth->priv_decode) { EVP_PKEY *tmp; PKCS8_PRIV_KEY_INFO *p8 = NULL; p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); if (!p8) goto err; tmp = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (tmp == NULL) goto err; EVP_PKEY_free(ret); ret = tmp; } else { ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB); goto err; } } *pp = p; if (a != NULL) (*a) = ret; return (ret); err: if ((ret != NULL) && ((a == NULL) || (*a != ret))) EVP_PKEY_free(ret); return (NULL); }