static int wrap_key(EVP_PKEY* pkey, int type, uint8_t** keyBlob, size_t* keyBlobLength) { /* * Find the length of each size. Public key is not needed anymore * but must be kept for alignment purposes. */ int publicLen = 0; int privateLen = i2d_PrivateKey(pkey, NULL); if (privateLen <= 0) { ALOGE("private key size was too big"); return -1; } /* int type + int size + private key data + int size + public key data */ *keyBlobLength = get_softkey_header_size() + sizeof(type) + sizeof(publicLen) + privateLen + sizeof(privateLen) + publicLen; // derData will be returned to the caller, so allocate it with malloc. UniquePtr<unsigned char, Malloc_Free> derData( static_cast<unsigned char*>(malloc(*keyBlobLength))); if (derData.get() == NULL) { ALOGE("could not allocate memory for key blob"); return -1; } unsigned char* p = derData.get(); /* Write the magic value for software keys. */ p = add_softkey_header(p, *keyBlobLength); /* Write key type to allocated buffer */ for (int i = sizeof(type) - 1; i >= 0; i--) { *p++ = (type >> (8 * i)) & 0xFF; } /* Write public key to allocated buffer */ for (int i = sizeof(publicLen) - 1; i >= 0; i--) { *p++ = (publicLen >> (8 * i)) & 0xFF; } /* Write private key to allocated buffer */ for (int i = sizeof(privateLen) - 1; i >= 0; i--) { *p++ = (privateLen >> (8 * i)) & 0xFF; } if (i2d_PrivateKey(pkey, &p) != privateLen) { logOpenSSLError("wrap_key"); return -1; } *keyBlob = derData.release(); return 0; }
static int wrap_key(EVP_PKEY* pkey, int type, uint8_t** keyBlob, size_t* keyBlobLength) { /* Find the length of each size */ int publicLen = i2d_PublicKey(pkey, NULL); int privateLen = i2d_PrivateKey(pkey, NULL); if (privateLen <= 0 || publicLen <= 0) { ALOGE("private or public key size was too big"); return -1; } /* int type + int size + private key data + int size + public key data */ *keyBlobLength = get_softkey_header_size() + sizeof(int) + sizeof(int) + privateLen + sizeof(int) + publicLen; UniquePtr<unsigned char[]> derData(new unsigned char[*keyBlobLength]); if (derData.get() == NULL) { ALOGE("could not allocate memory for key blob"); return -1; } unsigned char* p = derData.get(); /* Write the magic value for software keys. */ p = add_softkey_header(p, *keyBlobLength); /* Write key type to allocated buffer */ for (int i = sizeof(int) - 1; i >= 0; i--) { *p++ = (type >> (8*i)) & 0xFF; } /* Write public key to allocated buffer */ for (int i = sizeof(int) - 1; i >= 0; i--) { *p++ = (publicLen >> (8*i)) & 0xFF; } if (i2d_PublicKey(pkey, &p) != publicLen) { logOpenSSLError("wrap_key"); return -1; } /* Write private key to allocated buffer */ for (int i = sizeof(int) - 1; i >= 0; i--) { *p++ = (privateLen >> (8*i)) & 0xFF; } if (i2d_PrivateKey(pkey, &p) != privateLen) { logOpenSSLError("wrap_key"); return -1; } *keyBlob = derData.release(); return 0; }
static EVP_PKEY* unwrap_key(const uint8_t* keyBlob, const size_t keyBlobLength) { long publicLen = 0; long privateLen = 0; const uint8_t* p = keyBlob; const uint8_t *const end = keyBlob + keyBlobLength; if (keyBlob == NULL) { ALOGE("supplied key blob was NULL"); return NULL; } // Should be large enough for: // int32 magic, int32 type, int32 pubLen, char* pub, int32 privLen, char* priv if (keyBlobLength < (get_softkey_header_size() + sizeof(int) + sizeof(int) + 1 + sizeof(int) + 1)) { ALOGE("key blob appears to be truncated"); return NULL; } if (!is_softkey(p, keyBlobLength)) { ALOGE("cannot read key; it was not made by this keymaster"); return NULL; } p += get_softkey_header_size(); int type = 0; for (size_t i = 0; i < sizeof(int); i++) { type = (type << 8) | *p++; } Unique_EVP_PKEY pkey(EVP_PKEY_new()); if (pkey.get() == NULL) { logOpenSSLError("unwrap_key"); return NULL; } for (size_t i = 0; i < sizeof(int); i++) { publicLen = (publicLen << 8) | *p++; } if (p + publicLen > end) { ALOGE("public key length encoding error: size=%ld, end=%d", publicLen, end - p); return NULL; } EVP_PKEY* tmp = pkey.get(); d2i_PublicKey(type, &tmp, &p, publicLen); if (end - p < 2) { ALOGE("private key truncated"); return NULL; } for (size_t i = 0; i < sizeof(int); i++) { privateLen = (privateLen << 8) | *p++; } if (p + privateLen > end) { ALOGE("private key length encoding error: size=%ld, end=%d", privateLen, end - p); return NULL; } d2i_PrivateKey(type, &tmp, &p, privateLen); return pkey.release(); }