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; }
static int openssl_generate_keypair(const keymaster_device_t* dev, const keymaster_keypair_t key_type, const void* key_params, uint8_t** keyBlob, size_t* keyBlobLength) { ssize_t privateLen, publicLen; if (key_type != TYPE_RSA) { ALOGW("Unsupported key type %d", key_type); return -1; } else if (key_params == NULL) { ALOGW("key_params == null"); return -1; } keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params; Unique_BIGNUM bn(BN_new()); if (bn.get() == NULL) { logOpenSSLError("openssl_generate_keypair"); return -1; } if (BN_set_word(bn.get(), rsa_params->public_exponent) == 0) { logOpenSSLError("openssl_generate_keypair"); return -1; } /* initialize RSA */ Unique_RSA rsa(RSA_new()); if (rsa.get() == NULL) { logOpenSSLError("openssl_generate_keypair"); return -1; } if (!RSA_generate_key_ex(rsa.get(), rsa_params->modulus_size, bn.get(), NULL) || RSA_check_key(rsa.get()) < 0) { logOpenSSLError("openssl_generate_keypair"); return -1; } /* assign to EVP */ Unique_EVP_PKEY pkey(EVP_PKEY_new()); if (pkey.get() == NULL) { logOpenSSLError("openssl_generate_keypair"); return -1; } if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) == 0) { logOpenSSLError("openssl_generate_keypair"); return -1; } OWNERSHIP_TRANSFERRED(rsa); if (wrap_key(pkey.get(), EVP_PKEY_RSA, keyBlob, keyBlobLength)) { return -1; } return 0; }
static int qcom_km_get_keypair_public(const keymaster_device* dev, const uint8_t* keyBlob, const size_t keyBlobLength, uint8_t** x509_data, size_t* x509_data_length) { struct qcom_km_key_blob * keyblob_ptr = (struct qcom_km_key_blob *)keyBlob; if (x509_data == NULL || x509_data_length == NULL) { ALOGE("Output public key buffer == NULL"); return -1; } if (keyBlob == NULL) { ALOGE("Supplied key blob was NULL"); return -1; } // Should be large enough for keyblob data: if (keyBlobLength < (sizeof(qcom_km_key_blob_t))) { ALOGE("key blob appears to be truncated"); return -1; } if (keyblob_ptr->magic_num != KM_MAGIC_NUM) { ALOGE("Cannot read key; it was not made by this keymaster"); return -1; } if (keyblob_ptr->public_exponent_size == 0 ) { ALOGE("Key blob appears to have incorrect exponent length"); return -1; } if (keyblob_ptr->modulus_size == 0 ) { ALOGE("Key blob appears to have incorrect modulus length"); return -1; } Unique_RSA rsa(RSA_new()); if (rsa.get() == NULL) { ALOGE("Could not allocate RSA structure"); return -1; } rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(keyblob_ptr->modulus), keyblob_ptr->modulus_size, NULL); if (rsa->n == NULL) { ALOGE("Failed to initialize modulus"); return -1; } rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(&keyblob_ptr->public_exponent), keyblob_ptr->public_exponent_size, NULL); if (rsa->e == NULL) { ALOGE("Failed to initialize public exponent"); return -1; } Unique_EVP_PKEY pkey(EVP_PKEY_new()); if (pkey.get() == NULL) { ALOGE("Could not allocate EVP_PKEY structure"); return -1; } if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) { ALOGE("Failed to assign rsa parameters \n"); return -1; } OWNERSHIP_TRANSFERRED(rsa); int len = i2d_PUBKEY(pkey.get(), NULL); if (len <= 0) { ALOGE("Len returned is < 0 len = %d", len); return -1; } UniquePtr<uint8_t> key(static_cast<uint8_t*>(malloc(len))); if (key.get() == NULL) { ALOGE("Could not allocate memory for public key data"); return -1; } unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get()); if (i2d_PUBKEY(pkey.get(), &tmp) != len) { ALOGE("Len 2 returned is < 0 len = %d", len); return -1; } *x509_data_length = len; *x509_data = key.release(); return 0; }