123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Host functions for keys.
- */
- #include <stdio.h>
- #include <openssl/pem.h>
- #include "2sysincludes.h"
- #include "2common.h"
- #include "2rsa.h"
- #include "2sha.h"
- #include "vb21_common.h"
- #include "host_common.h"
- #include "host_key2.h"
- #include "host_misc.h"
- const struct vb2_text_vs_enum vb2_text_vs_sig[] = {
- {"RSA1024", VB2_SIG_RSA1024},
- {"RSA2048", VB2_SIG_RSA2048},
- {"RSA4096", VB2_SIG_RSA4096},
- {"RSA8192", VB2_SIG_RSA8192},
- {0, 0}
- };
- const struct vb2_text_vs_enum vb2_text_vs_hash[] = {
- {"SHA1", VB2_HASH_SHA1},
- {"SHA256", VB2_HASH_SHA256},
- {"SHA512", VB2_HASH_SHA512},
- {0, 0}
- };
- const struct vb2_text_vs_enum vb2_text_vs_crypto[] = {
- {"RSA1024 SHA1", VB2_ALG_RSA1024_SHA1},
- {"RSA1024 SHA256", VB2_ALG_RSA1024_SHA256},
- {"RSA1024 SHA512", VB2_ALG_RSA1024_SHA512},
- {"RSA2048 SHA1", VB2_ALG_RSA2048_SHA1},
- {"RSA2048 SHA256", VB2_ALG_RSA2048_SHA256},
- {"RSA2048 SHA512", VB2_ALG_RSA2048_SHA512},
- {"RSA4096 SHA1", VB2_ALG_RSA4096_SHA1},
- {"RSA4096 SHA256", VB2_ALG_RSA4096_SHA256},
- {"RSA4096 SHA512", VB2_ALG_RSA4096_SHA512},
- {"RSA8192 SHA1", VB2_ALG_RSA8192_SHA1},
- {"RSA8192 SHA256", VB2_ALG_RSA8192_SHA256},
- {"RSA8192 SHA512", VB2_ALG_RSA8192_SHA512},
- {0, 0}
- };
- const struct vb2_text_vs_enum *vb2_lookup_by_num(
- const struct vb2_text_vs_enum *table,
- const unsigned int num)
- {
- for (; table->name; table++)
- if (table->num == num)
- return table;
- return 0;
- }
- const struct vb2_text_vs_enum *vb2_lookup_by_name(
- const struct vb2_text_vs_enum *table,
- const char *name)
- {
- for (; table->name; table++)
- if (!strcasecmp(table->name, name))
- return table;
- return 0;
- }
- const char *vb2_get_sig_algorithm_name(enum vb2_signature_algorithm sig_alg)
- {
- const struct vb2_text_vs_enum *entry =
- vb2_lookup_by_num(vb2_text_vs_sig, sig_alg);
- return entry ? entry->name : VB2_INVALID_ALG_NAME;
- }
- const char *vb2_get_crypto_algorithm_name(enum vb2_crypto_algorithm alg)
- {
- const struct vb2_text_vs_enum *entry =
- vb2_lookup_by_num(vb2_text_vs_crypto, alg);
- return entry ? entry->name : VB2_INVALID_ALG_NAME;
- }
- void vb2_private_key_free(struct vb2_private_key *key)
- {
- if (!key)
- return;
- if (key->rsa_private_key)
- RSA_free(key->rsa_private_key);
- if (key->desc)
- free(key->desc);
- free(key);
- }
- int vb21_private_key_unpack(struct vb2_private_key **key_ptr,
- const uint8_t *buf,
- uint32_t size)
- {
- const struct vb21_packed_private_key *pkey =
- (const struct vb21_packed_private_key *)buf;
- struct vb2_private_key *key;
- const unsigned char *start;
- uint32_t min_offset = 0;
- *key_ptr = NULL;
- /*
- * Check magic number.
- *
- * TODO: If it doesn't match, pass through to the old packed key format.
- */
- if (pkey->c.magic != VB21_MAGIC_PACKED_PRIVATE_KEY)
- return VB2_ERROR_UNPACK_PRIVATE_KEY_MAGIC;
- if (vb21_verify_common_header(buf, size))
- return VB2_ERROR_UNPACK_PRIVATE_KEY_HEADER;
- /* Make sure key data is inside */
- if (vb21_verify_common_member(pkey, &min_offset,
- pkey->key_offset, pkey->key_size))
- return VB2_ERROR_UNPACK_PRIVATE_KEY_DATA;
- /*
- * Check for compatible version. No need to check minor version, since
- * that's compatible across readers matching the major version, and we
- * haven't added any new fields.
- */
- if (pkey->c.struct_version_major !=
- VB21_PACKED_PRIVATE_KEY_VERSION_MAJOR)
- return VB2_ERROR_UNPACK_PRIVATE_KEY_STRUCT_VERSION;
- /* Allocate the new key */
- key = calloc(1, sizeof(*key));
- if (!key)
- return VB2_ERROR_UNPACK_PRIVATE_KEY_ALLOC;
- /* Copy key algorithms and ID */
- key->sig_alg = pkey->sig_alg;
- key->hash_alg = pkey->hash_alg;
- key->id = pkey->id;
- /* Unpack RSA key */
- if (pkey->sig_alg == VB2_SIG_NONE) {
- if (pkey->key_size != 0) {
- free(key);
- return VB2_ERROR_UNPACK_PRIVATE_KEY_HASH;
- }
- } else {
- start = (const unsigned char *)(buf + pkey->key_offset);
- key->rsa_private_key = d2i_RSAPrivateKey(0, &start,
- pkey->key_size);
- if (!key->rsa_private_key) {
- free(key);
- return VB2_ERROR_UNPACK_PRIVATE_KEY_RSA;
- }
- }
- /* Key description */
- if (pkey->c.desc_size) {
- if (vb2_private_key_set_desc(
- key, (const char *)(buf + pkey->c.fixed_size))) {
- vb2_private_key_free(key);
- return VB2_ERROR_UNPACK_PRIVATE_KEY_DESC;
- }
- }
- *key_ptr = key;
- return VB2_SUCCESS;
- }
- int vb21_private_key_read(struct vb2_private_key **key_ptr,
- const char *filename)
- {
- uint32_t size = 0;
- uint8_t *buf = NULL;
- int rv;
- *key_ptr = NULL;
- rv = vb2_read_file(filename, &buf, &size);
- if (rv)
- return rv;
- rv = vb21_private_key_unpack(key_ptr, buf, size);
- free(buf);
- return rv;
- }
- int vb2_private_key_read_pem(struct vb2_private_key **key_ptr,
- const char *filename)
- {
- struct vb2_private_key *key;
- FILE *f;
- *key_ptr = NULL;
- /* Allocate the new key */
- key = calloc(1, sizeof(*key));
- if (!key)
- return VB2_ERROR_READ_PEM_ALLOC;
- /* Read private key */
- f = fopen(filename, "rb");
- if (!f) {
- free(key);
- return VB2_ERROR_READ_PEM_FILE_OPEN;
- }
- key->rsa_private_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
- fclose(f);
- if (!key->rsa_private_key) {
- free(key);
- return VB2_ERROR_READ_PEM_RSA;
- }
- *key_ptr = key;
- return VB2_SUCCESS;
- }
- int vb2_private_key_set_desc(struct vb2_private_key *key, const char *desc)
- {
- if (key->desc)
- free(key->desc);
- if (desc) {
- key->desc = strdup(desc);
- if (!key->desc)
- return VB2_ERROR_PRIVATE_KEY_SET_DESC;
- } else {
- key->desc = NULL;
- }
- return VB2_SUCCESS;
- }
- int vb21_private_key_write(const struct vb2_private_key *key,
- const char *filename)
- {
- struct vb21_packed_private_key pkey = {
- .c.magic = VB21_MAGIC_PACKED_PRIVATE_KEY,
- .c.struct_version_major = VB21_PACKED_PRIVATE_KEY_VERSION_MAJOR,
- .c.struct_version_minor = VB21_PACKED_PRIVATE_KEY_VERSION_MINOR,
- .c.fixed_size = sizeof(pkey),
- .sig_alg = key->sig_alg,
- .hash_alg = key->hash_alg,
- .id = key->id,
- };
- uint8_t *buf;
- uint8_t *rsabuf = NULL;
- int rsalen = 0;
- int rv;
- memcpy(&pkey.id, &key->id, sizeof(pkey.id));
- pkey.c.desc_size = vb2_desc_size(key->desc);
- if (key->sig_alg != VB2_SIG_NONE) {
- /* Pack RSA key */
- rsalen = i2d_RSAPrivateKey(key->rsa_private_key, &rsabuf);
- if (rsalen <= 0 || !rsabuf)
- return VB2_ERROR_PRIVATE_KEY_WRITE_RSA;
- }
- pkey.key_offset = pkey.c.fixed_size + pkey.c.desc_size;
- pkey.key_size = roundup32(rsalen);
- pkey.c.total_size = pkey.key_offset + pkey.key_size;
- /* Pack private key */
- buf = calloc(1, pkey.c.total_size);
- if (!buf) {
- free(rsabuf);
- return VB2_ERROR_PRIVATE_KEY_WRITE_ALLOC;
- }
- memcpy(buf, &pkey, sizeof(pkey));
- /* strcpy() is ok here because we checked the length above */
- if (pkey.c.desc_size)
- strcpy((char *)buf + pkey.c.fixed_size, key->desc);
- if (rsabuf) {
- memcpy(buf + pkey.key_offset, rsabuf, rsalen);
- free(rsabuf);
- }
- rv = vb21_write_object(filename, buf);
- free(buf);
- return rv ? VB2_ERROR_PRIVATE_KEY_WRITE_FILE : VB2_SUCCESS;
- }
- int vb2_private_key_hash(const struct vb2_private_key **key_ptr,
- enum vb2_hash_algorithm hash_alg)
- {
- *key_ptr = NULL;
- switch (hash_alg) {
- #if VB2_SUPPORT_SHA1
- case VB2_HASH_SHA1:
- {
- static const struct vb2_private_key key = {
- .hash_alg = VB2_HASH_SHA1,
- .sig_alg = VB2_SIG_NONE,
- .desc = "Unsigned SHA1",
- .id = VB2_ID_NONE_SHA1,
- };
- *key_ptr = &key;
- return VB2_SUCCESS;
- }
- #endif
- #if VB2_SUPPORT_SHA256
- case VB2_HASH_SHA256:
- {
- static const struct vb2_private_key key = {
- .hash_alg = VB2_HASH_SHA256,
- .sig_alg = VB2_SIG_NONE,
- .desc = "Unsigned SHA-256",
- .id = VB2_ID_NONE_SHA256,
- };
- *key_ptr = &key;
- return VB2_SUCCESS;
- }
- #endif
- #if VB2_SUPPORT_SHA512
- case VB2_HASH_SHA512:
- {
- static const struct vb2_private_key key = {
- .hash_alg = VB2_HASH_SHA512,
- .sig_alg = VB2_SIG_NONE,
- .desc = "Unsigned SHA-512",
- .id = VB2_ID_NONE_SHA512,
- };
- *key_ptr = &key;
- return VB2_SUCCESS;
- }
- #endif
- default:
- return VB2_ERROR_PRIVATE_KEY_HASH;
- }
- }
- int vb2_public_key_alloc(struct vb2_public_key **key_ptr,
- enum vb2_signature_algorithm sig_alg)
- {
- struct vb2_public_key *key;
- uint32_t key_data_size = vb2_packed_key_size(sig_alg);
- /* The buffer contains the key, its ID, and its packed data */
- uint32_t buf_size = sizeof(*key) + sizeof(struct vb2_id) +
- key_data_size;
- if (!key_data_size)
- return VB2_ERROR_PUBLIC_KEY_ALLOC_SIZE;
- key = calloc(1, buf_size);
- if (!key)
- return VB2_ERROR_PUBLIC_KEY_ALLOC;
- key->id = (struct vb2_id *)(key + 1);
- key->sig_alg = sig_alg;
- *key_ptr = key;
- return VB2_SUCCESS;
- }
- void vb2_public_key_free(struct vb2_public_key *key)
- {
- if (!key)
- return;
- if (key->desc)
- free((void *)key->desc);
- free(key);
- }
- uint8_t *vb2_public_key_packed_data(struct vb2_public_key *key)
- {
- return (uint8_t *)(key->id + 1);
- }
- int vb2_public_key_read_keyb(struct vb2_public_key **key_ptr,
- const char *filename)
- {
- struct vb2_public_key *key = NULL;
- uint8_t *key_data, *key_buf;
- uint32_t key_size;
- enum vb2_signature_algorithm sig_alg;
- *key_ptr = NULL;
- if (vb2_read_file(filename, &key_data, &key_size))
- return VB2_ERROR_READ_KEYB_DATA;
- /* Guess the signature algorithm from the key size */
- for (sig_alg = VB2_SIG_RSA1024; sig_alg <= VB2_SIG_RSA8192; sig_alg++) {
- if (key_size == vb2_packed_key_size(sig_alg))
- break;
- }
- if (sig_alg > VB2_SIG_RSA8192) {
- free(key_data);
- return VB2_ERROR_READ_KEYB_SIZE;
- }
- if (vb2_public_key_alloc(&key, sig_alg)) {
- free(key_data);
- return VB2_ERROR_READ_KEYB_ALLOC;
- }
- /* Copy data from the file buffer to the public key buffer */
- key_buf = vb2_public_key_packed_data(key);
- memcpy(key_buf, key_data, key_size);
- free(key_data);
- if (vb2_unpack_key_data(key, key_buf, key_size)) {
- vb2_public_key_free(key);
- return VB2_ERROR_READ_KEYB_UNPACK;
- }
- *key_ptr = key;
- return VB2_SUCCESS;
- }
- int vb2_public_key_set_desc(struct vb2_public_key *key, const char *desc)
- {
- if (key->desc)
- free((void *)key->desc);
- if (desc) {
- key->desc = strdup(desc);
- if (!key->desc)
- return VB2_ERROR_PUBLIC_KEY_SET_DESC;
- } else {
- key->desc = NULL;
- }
- return VB2_SUCCESS;
- }
- int vb21_packed_key_read(struct vb21_packed_key **key_ptr,
- const char *filename)
- {
- struct vb2_public_key key;
- uint8_t *buf;
- uint32_t size;
- *key_ptr = NULL;
- if (vb2_read_file(filename, &buf, &size))
- return VB2_ERROR_READ_PACKED_KEY_DATA;
- /* Sanity check: make sure key unpacks properly */
- if (vb21_unpack_key(&key, buf, size))
- return VB2_ERROR_READ_PACKED_KEY;
- *key_ptr = (struct vb21_packed_key *)buf;
- return VB2_SUCCESS;
- }
- int vb21_public_key_pack(struct vb21_packed_key **key_ptr,
- const struct vb2_public_key *pubk)
- {
- struct vb21_packed_key key = {
- .c.magic = VB21_MAGIC_PACKED_KEY,
- .c.struct_version_major = VB21_PACKED_KEY_VERSION_MAJOR,
- .c.struct_version_minor = VB21_PACKED_KEY_VERSION_MINOR,
- };
- uint8_t *buf;
- uint32_t *buf32;
- *key_ptr = NULL;
- /* Calculate sizes and offsets */
- key.c.fixed_size = sizeof(key);
- key.c.desc_size = vb2_desc_size(pubk->desc);
- key.key_offset = key.c.fixed_size + key.c.desc_size;
- if (pubk->sig_alg != VB2_SIG_NONE) {
- key.key_size = vb2_packed_key_size(pubk->sig_alg);
- if (!key.key_size)
- return VB2_ERROR_PUBLIC_KEY_PACK_SIZE;
- }
- key.c.total_size = key.key_offset + key.key_size;
- /* Copy/initialize fields */
- key.key_version = pubk->version;
- key.sig_alg = pubk->sig_alg;
- key.hash_alg = pubk->hash_alg;
- key.id = *pubk->id;
- /* Allocate the new buffer */
- buf = calloc(1, key.c.total_size);
- /* Copy data into the buffer */
- memcpy(buf, &key, sizeof(key));
- /* strcpy() is safe because we allocated above based on strlen() */
- if (pubk->desc && *pubk->desc) {
- strcpy((char *)(buf + key.c.fixed_size), pubk->desc);
- buf[key.c.fixed_size + key.c.desc_size - 1] = 0;
- }
- if (pubk->sig_alg != VB2_SIG_NONE) {
- /* Re-pack the key arrays */
- buf32 = (uint32_t *)(buf + key.key_offset);
- buf32[0] = pubk->arrsize;
- buf32[1] = pubk->n0inv;
- memcpy(buf32 + 2, pubk->n, pubk->arrsize * sizeof(uint32_t));
- memcpy(buf32 + 2 + pubk->arrsize, pubk->rr,
- pubk->arrsize * sizeof(uint32_t));
- }
- *key_ptr = (struct vb21_packed_key *)buf;
- return VB2_SUCCESS;
- }
- int vb2_public_key_hash(struct vb2_public_key *key,
- enum vb2_hash_algorithm hash_alg)
- {
- switch (hash_alg) {
- #if VB2_SUPPORT_SHA1
- case VB2_HASH_SHA1:
- key->desc = "Unsigned SHA1";
- break;
- #endif
- #if VB2_SUPPORT_SHA256
- case VB2_HASH_SHA256:
- key->desc = "Unsigned SHA-256";
- break;
- #endif
- #if VB2_SUPPORT_SHA512
- case VB2_HASH_SHA512:
- key->desc = "Unsigned SHA-512";
- break;
- #endif
- default:
- return VB2_ERROR_PUBLIC_KEY_HASH;
- }
- key->sig_alg = VB2_SIG_NONE;
- key->hash_alg = hash_alg;
- key->id = vb2_hash_id(hash_alg);
- return VB2_SUCCESS;
- }
- enum vb2_signature_algorithm vb2_rsa_sig_alg(struct rsa_st *rsa)
- {
- int bits = BN_num_bits(rsa->n);
- switch (bits) {
- case 1024:
- return VB2_SIG_RSA1024;
- case 2048:
- return VB2_SIG_RSA2048;
- case 4096:
- return VB2_SIG_RSA4096;
- case 8192:
- return VB2_SIG_RSA8192;
- }
- /* no clue */
- return VB2_SIG_INVALID;
- }
- int vb21_public_key_write(const struct vb2_public_key *key,
- const char *filename)
- {
- struct vb21_packed_key *pkey;
- int ret;
- ret = vb21_public_key_pack(&pkey, key);
- if (ret)
- return ret;
- ret = vb21_write_object(filename, pkey);
- free(pkey);
- return ret;
- }
|