static void keyblock_tests(const char *keys_dir) { struct vb2_public_key *pubk2048, *pubk4096, *pubk8192, pubkhash; struct vb2_private_key *prik4096, *prik8192; struct vb2_packed_key *pak, *pakgood; struct vb2_keyblock *kb; const struct vb2_private_key *prikhash; const struct vb2_private_key *prik[2]; char fname[1024]; const char test_desc[] = "Test keyblock"; uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES] __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); struct vb2_workbuf wb; vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); /* Read keys */ sprintf(fname, "%s/key_rsa2048.keyb", keys_dir); TEST_SUCC(vb2_public_key_read_keyb(&pubk2048, fname), "Read public key 2"); vb2_public_key_set_desc(pubk2048, "Test RSA2048 public key"); pubk2048->hash_alg = VB2_HASH_SHA256; sprintf(fname, "%s/key_rsa4096.keyb", keys_dir); TEST_SUCC(vb2_public_key_read_keyb(&pubk4096, fname), "Read public key 1"); vb2_public_key_set_desc(pubk4096, "Test RSA4096 public key"); pubk4096->hash_alg = VB2_HASH_SHA256; sprintf(fname, "%s/key_rsa8192.keyb", keys_dir); TEST_SUCC(vb2_public_key_read_keyb(&pubk8192, fname), "Read public key 2"); vb2_public_key_set_desc(pubk8192, "Test RSA8192 public key"); pubk8192->hash_alg = VB2_HASH_SHA512; sprintf(fname, "%s/key_rsa4096.pem", keys_dir); TEST_SUCC(vb2_private_key_read_pem(&prik4096, fname), "Read private key 2"); vb2_private_key_set_desc(prik4096, "Test RSA4096 private key"); prik4096->sig_alg = VB2_SIG_RSA4096; prik4096->hash_alg = VB2_HASH_SHA256; sprintf(fname, "%s/key_rsa8192.pem", keys_dir); TEST_SUCC(vb2_private_key_read_pem(&prik8192, fname), "Read private key 1"); vb2_private_key_set_desc(prik8192, "Test RSA8192 private key"); prik8192->sig_alg = VB2_SIG_RSA8192; prik8192->hash_alg = VB2_HASH_SHA512; TEST_SUCC(vb2_private_key_hash(&prikhash, VB2_HASH_SHA512), "Create private hash key"); TEST_SUCC(vb2_public_key_hash(&pubkhash, VB2_HASH_SHA512), "Create public hash key"); TEST_SUCC(vb2_public_key_pack(&pakgood, pubk2048), "Test packed key"); /* Sign a keyblock with one key */ prik[0] = prik4096; TEST_SUCC(vb2_keyblock_create(&kb, pubk2048, prik, 1, 0x1234, NULL), "Keyblock single"); TEST_PTR_NEQ(kb, NULL, " kb_ptr"); TEST_SUCC(vb2_verify_keyblock(kb, kb->c.total_size, pubk4096, &wb), " verify"); TEST_EQ(strcmp(vb2_common_desc(kb), pubk2048->desc), 0, " desc"); TEST_EQ(kb->flags, 0x1234, " flags"); pak = (struct vb2_packed_key *)((uint8_t *)kb + kb->key_offset); TEST_EQ(0, memcmp(pak, pakgood, pakgood->c.total_size), " data key"); free(kb); /* Sign a keyblock with two keys */ prik[0] = prik8192; prik[1] = prikhash; TEST_SUCC(vb2_keyblock_create(&kb, pubk4096, prik, 2, 0, test_desc), "Keyblock multiple"); TEST_SUCC(vb2_verify_keyblock(kb, kb->c.total_size, pubk8192, &wb), " verify 1"); TEST_SUCC(vb2_verify_keyblock(kb, kb->c.total_size, &pubkhash, &wb), " verify 2"); TEST_EQ(strcmp(vb2_common_desc(kb), test_desc), 0, " desc"); TEST_EQ(kb->flags, 0, " flags"); free(kb); /* Test errors */ prik[0] = prik8192; prik8192->hash_alg = VB2_HASH_INVALID; TEST_EQ(vb2_keyblock_create(&kb, pubk4096, prik, 1, 0, NULL), VB2_KEYBLOCK_CREATE_SIG_SIZE, "Keyblock bad sig size"); TEST_PTR_EQ(kb, NULL, " kb_ptr"); prik[0] = prik4096; pubk4096->sig_alg = VB2_SIG_INVALID; TEST_EQ(vb2_keyblock_create(&kb, pubk4096, prik, 1, 0, NULL), VB2_KEYBLOCK_CREATE_DATA_KEY, "Keyblock bad data key"); /* Free keys */ free(pakgood); vb2_public_key_free(pubk2048); vb2_public_key_free(pubk4096); vb2_public_key_free(pubk8192); vb2_private_key_free(prik4096); vb2_private_key_free(prik8192); }
static int vb2_make_keypair() { struct vb2_private_key *privkey = 0; struct vb2_public_key *pubkey = 0; RSA *rsa_key = 0; uint8_t *keyb_data = 0; uint32_t keyb_size; enum vb2_signature_algorithm sig_alg; uint8_t *pubkey_buf = 0; FILE *fp; int ret = 1; fp = fopen(infile, "rb"); if (!fp) { fprintf(stderr, "Unable to open %s\n", infile); goto done; } rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); if (!rsa_key) { fprintf(stderr, "Unable to read RSA key from %s\n", infile); goto done; } sig_alg = vb2_rsa_sig_alg(rsa_key); if (sig_alg == VB2_SIG_INVALID) { fprintf(stderr, "Unsupported sig algorithm in RSA key\n"); goto done; } /* Create the private key */ privkey = calloc(1, sizeof(*privkey)); if (!privkey) { fprintf(stderr, "Unable to allocate the private key\n"); goto done; } privkey->rsa_private_key = rsa_key; privkey->sig_alg = sig_alg; privkey->hash_alg = opt_hash_alg; privkey->guid = opt_guid; if (opt_desc && vb2_private_key_set_desc(privkey, opt_desc)) { fprintf(stderr, "Unable to set the private key description\n"); goto done; } /* Write it out */ strcpy(outext, ".vbprik2"); if (vb2_private_key_write(privkey, outfile)) { fprintf(stderr, "unable to write private key\n"); goto done; } fprintf(stderr, "wrote %s\n", outfile); /* Create the public key */ if (vb2_public_key_alloc(&pubkey, sig_alg)) { fprintf(stderr, "Unable to allocate the public key\n"); goto done; } /* Extract the keyb blob */ if (vb_keyb_from_rsa(rsa_key, &keyb_data, &keyb_size)) { fprintf(stderr, "Couldn't extract the public key\n"); goto done; } /* * Copy the keyb blob to the public key's buffer, because that's where * vb2_unpack_key_data() and vb2_public_key_pack() expect to find it. */ pubkey_buf = vb2_public_key_packed_data(pubkey); memcpy(pubkey_buf, keyb_data, keyb_size); /* Fill in the internal struct pointers */ if (vb2_unpack_key_data(pubkey, pubkey_buf, keyb_size)) { fprintf(stderr, "Unable to unpack the public key blob\n"); goto done; } pubkey->hash_alg = opt_hash_alg; pubkey->version = opt_version; memcpy((struct vb2_guid *)pubkey->guid, &opt_guid, sizeof(opt_guid)); if (opt_desc && vb2_public_key_set_desc(pubkey, opt_desc)) { fprintf(stderr, "Unable to set pubkey description\n"); goto done; } /* Write it out */ strcpy(outext, ".vbpubk2"); if (vb2_public_key_write(pubkey, outfile)) { fprintf(stderr, "unable to write public key\n"); goto done; } fprintf(stderr, "wrote %s\n", outfile); ret = 0; done: RSA_free(rsa_key); if (privkey) /* prevent double-free */ privkey->rsa_private_key = 0; vb2_private_key_free(privkey); vb2_public_key_free(pubkey); free(keyb_data); return ret; }
static int vb2_make_keypair() { struct vb2_private_key *privkey = 0; struct vb2_public_key *pubkey = 0; RSA *rsa_key = 0; uint8_t *keyb_data = 0; uint32_t keyb_size; enum vb2_signature_algorithm sig_alg; uint8_t *pubkey_buf = 0; int has_priv = 0; FILE *fp; int ret = 1; fp = fopen(infile, "rb"); if (!fp) { fprintf(stderr, "Unable to open %s\n", infile); goto done; } rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); if (!rsa_key) { /* Check if the PEM contains only a public key */ fseek(fp, 0, SEEK_SET); rsa_key = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); } fclose(fp); if (!rsa_key) { fprintf(stderr, "Unable to read RSA key from %s\n", infile); goto done; } /* Public keys doesn't have the private exponent */ has_priv = !!rsa_key->d; if (!has_priv) fprintf(stderr, "%s has a public key only.\n", infile); sig_alg = vb2_rsa_sig_alg(rsa_key); if (sig_alg == VB2_SIG_INVALID) { fprintf(stderr, "Unsupported sig algorithm in RSA key\n"); goto done; } if (has_priv) { /* Create the private key */ privkey = calloc(1, sizeof(*privkey)); if (!privkey) { fprintf(stderr, "Unable to allocate the private key\n"); goto done; } privkey->rsa_private_key = rsa_key; privkey->sig_alg = sig_alg; privkey->hash_alg = opt_hash_alg; if (opt_desc && vb2_private_key_set_desc(privkey, opt_desc)) { fprintf(stderr, "Unable to set the private key description\n"); goto done; } } /* Create the public key */ if (vb2_public_key_alloc(&pubkey, sig_alg)) { fprintf(stderr, "Unable to allocate the public key\n"); goto done; } /* Extract the keyb blob */ if (vb_keyb_from_rsa(rsa_key, &keyb_data, &keyb_size)) { fprintf(stderr, "Couldn't extract the public key\n"); goto done; } /* * Copy the keyb blob to the public key's buffer, because that's where * vb2_unpack_key_data() and vb2_public_key_pack() expect to find it. */ pubkey_buf = vb2_public_key_packed_data(pubkey); memcpy(pubkey_buf, keyb_data, keyb_size); /* Fill in the internal struct pointers */ if (vb2_unpack_key_data(pubkey, pubkey_buf, keyb_size)) { fprintf(stderr, "Unable to unpack the public key blob\n"); goto done; } pubkey->hash_alg = opt_hash_alg; pubkey->version = opt_version; if (opt_desc && vb2_public_key_set_desc(pubkey, opt_desc)) { fprintf(stderr, "Unable to set pubkey description\n"); goto done; } /* Update the IDs */ if (!force_id) { uint8_t *digest = DigestBuf(keyb_data, keyb_size, SHA1_DIGEST_ALGORITHM); memcpy(&opt_id, digest, sizeof(opt_id)); free(digest); } memcpy((struct vb2_id *)pubkey->id, &opt_id, sizeof(opt_id)); /* Write them out */ if (has_priv) { privkey->id = opt_id; strcpy(outext, ".vbprik2"); if (vb2_private_key_write(privkey, outfile)) { fprintf(stderr, "unable to write private key\n"); goto done; } fprintf(stderr, "wrote %s\n", outfile); } strcpy(outext, ".vbpubk2"); if (vb2_public_key_write(pubkey, outfile)) { fprintf(stderr, "unable to write public key\n"); goto done; } fprintf(stderr, "wrote %s\n", outfile); ret = 0; done: RSA_free(rsa_key); if (privkey) /* prevent double-free */ privkey->rsa_private_key = 0; vb2_private_key_free(privkey); vb2_public_key_free(pubkey); free(keyb_data); return ret; }
int ft_sign_usbpd1(const char *name, uint8_t *buf, uint32_t len, void *data) { struct vb2_private_key *key_ptr = 0; struct vb2_signature *sig_ptr = 0; uint8_t *keyb_data = 0; uint32_t keyb_size; int retval = 1; uint32_t sig_size; uint32_t sig_offset; uint32_t pub_size; uint32_t pub_offset; uint32_t ro_size; uint32_t rw_size; uint32_t ro_offset; uint32_t rw_offset; uint32_t r; Debug("%s(): name %s\n", __func__, name); Debug("%s(): len 0x%08x (%d)\n", __func__, len, len); /* Get image locations */ if (!parse_size_opts(len, &ro_size, &rw_size, &ro_offset, &rw_offset)) goto done; /* Read the signing keypair file */ if (vb2_private_key_read_pem(&key_ptr, sign_option.pem_signpriv)) { fprintf(stderr, "Unable to read keypair from %s\n", sign_option.pem_signpriv); goto done; } /* Set the algs */ key_ptr->hash_alg = sign_option.hash_alg; key_ptr->sig_alg = vb2_rsa_sig_alg(key_ptr->rsa_private_key); if (key_ptr->sig_alg == VB2_SIG_INVALID) { fprintf(stderr, "Unsupported sig algorithm in RSA key\n"); goto done; } /* Figure out what needs signing */ sig_size = vb2_rsa_sig_size(key_ptr->sig_alg); if (rw_size < sig_size) { fprintf(stderr, "The RW image is too small to hold the signature" " (0x%08x < %08x)\n", rw_size, sig_size); goto done; } rw_size -= sig_size; sig_offset = rw_offset + rw_size; Debug("rw_size => 0x%08x\n", rw_size); Debug("rw_offset => 0x%08x\n", rw_offset); Debug("sig_size 0x%08x\n", sig_size); Debug("sig_offset 0x%08x\n", sig_offset); /* Sign the blob */ r = vb2_sign_data(&sig_ptr, buf + rw_offset, rw_size, key_ptr, "Bah"); if (r) { fprintf(stderr, "Unable to sign data (error 0x%08x, if that helps)\n", r); goto done; } /* Double-check the size */ if (sig_ptr->sig_size != sig_size) { fprintf(stderr, "ERROR: sig size is %d bytes, not %d as expected.\n", sig_ptr->sig_size, sig_size); goto done; } /* Okay, looking good. Update the signature. */ memcpy(buf + sig_offset, (uint8_t *)sig_ptr + sig_ptr->sig_offset, sig_ptr->sig_size); /* If there's no RO section, we're done. */ if (!ro_size) { retval = 0; goto done; } /* Otherwise, now update the public key */ if (vb_keyb_from_rsa(key_ptr->rsa_private_key, &keyb_data, &keyb_size)) { fprintf(stderr, "Couldn't extract the public key\n"); goto done; } Debug("keyb_size is 0x%x (%d):\n", keyb_size, keyb_size); /* * Of course the packed public key format is different. Why would you * think otherwise? Since the dawn of time, vboot has used this: * * uint32_t nwords size of RSA key in 32-bit words * uint32_t n0inv magic RSA n0inv * uint32_t n[nwords] magic RSA modulus little endian array * uint32_t rr[nwords] magic RSA R^2 little endian array * * But for no discernable reason, the usbpd1 format uses this: * * uint32_t n[nwords] magic RSA modulus little endian array * uint32_t rr[nwords] magic RSA R^2 little endian array * uint32_t n0inv magic RSA n0inv * * There's no nwords field, and n0inv is last insted of first. Sigh. */ pub_size = keyb_size - 4; /* align pubkey size to 16-byte boundary */ uint32_t pub_pad = pub_size; pub_size = (pub_size + 16) / 16 * 16; pub_pad = pub_size - pub_pad; pub_offset = ro_offset + ro_size - pub_size; if (ro_size < pub_size) { fprintf(stderr, "The RO image is too small to hold the public key" " (0x%08x < %08x)\n", ro_size, pub_size); goto done; } /* How many bytes in the arrays? */ uint32_t nbytes = 4 * (*(uint32_t *)keyb_data); /* Source offsets from keyb_data */ uint32_t src_ofs_n0inv = 4; uint32_t src_ofs_n = src_ofs_n0inv + 4; uint32_t src_ofs_rr = src_ofs_n + nbytes; /* Dest offsets from buf */ uint32_t dst_ofs_n = pub_offset + 0; uint32_t dst_ofs_rr = dst_ofs_n + nbytes; uint32_t dst_ofs_n0inv = dst_ofs_rr + nbytes; Debug("len 0x%08x ro_size 0x%08x ro_offset 0x%08x\n", len, ro_size, ro_offset); Debug("pub_size 0x%08x pub_offset 0x%08x nbytes 0x%08x\n", pub_size, pub_offset, nbytes); Debug("pub_pad 0x%08x\n", pub_pad); /* Copy n[nwords] */ memcpy(buf + dst_ofs_n, keyb_data + src_ofs_n, nbytes); /* Copy rr[nwords] */ memcpy(buf + dst_ofs_rr, keyb_data + src_ofs_rr, nbytes); /* Copy n0inv */ memcpy(buf + dst_ofs_n0inv, keyb_data + src_ofs_n0inv, 4); /* Pad with 0xff */ memset(buf + dst_ofs_n0inv + 4, 0xff, pub_pad); /* Finally */ retval = 0; done: if (key_ptr) vb2_private_key_free(key_ptr); if (keyb_data) free(keyb_data); return retval; }