diff options
Diffstat (limited to 'host/lib/util_misc.c')
-rw-r--r-- | host/lib/util_misc.c | 133 |
1 files changed, 125 insertions, 8 deletions
diff --git a/host/lib/util_misc.c b/host/lib/util_misc.c index 09df8eef..d2c21f52 100644 --- a/host/lib/util_misc.c +++ b/host/lib/util_misc.c @@ -5,6 +5,9 @@ * Miscellaneous functions for userspace vboot utilities. */ +#define OPENSSL_NO_SHA +#include <openssl/rsa.h> + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -15,12 +18,126 @@ #include "util_misc.h" #include "vboot_common.h" -void PrintPubKeySha1Sum(VbPublicKey* key) { - uint8_t* buf = ((uint8_t *)key) + key->key_offset; - uint64_t buflen = key->key_size; - uint8_t* digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM); - int i; - for (i=0; i<SHA1_DIGEST_SIZE; i++) - printf("%02x", digest[i]); - free(digest); +void PrintPubKeySha1Sum(VbPublicKey *key) +{ + uint8_t *buf = ((uint8_t *)key) + key->key_offset; + uint64_t buflen = key->key_size; + uint8_t *digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM); + int i; + for (i = 0; i < SHA1_DIGEST_SIZE; i++) + printf("%02x", digest[i]); + free(digest); +} + +int vb_keyb_from_rsa(struct rsa_st *rsa_private_key, + uint8_t **keyb_data, uint32_t *keyb_size) +{ + uint32_t i, nwords; + BIGNUM *N = NULL; + BIGNUM *Big1 = NULL, *Big2 = NULL, *Big32 = NULL, *BigMinus1 = NULL; + BIGNUM *B = NULL; + BIGNUM *N0inv = NULL, *R = NULL, *RR = NULL; + BIGNUM *RRTemp = NULL, *NnumBits = NULL; + BIGNUM *n = NULL, *rr = NULL; + BN_CTX *bn_ctx = BN_CTX_new(); + uint32_t n0invout; + uint32_t bufsize; + uint32_t *outbuf; + int retval = 1; + + /* Size of RSA key in 32-bit words */ + nwords = BN_num_bits(rsa_private_key->n) / 32; + + bufsize = (2 + nwords + nwords) * sizeof(uint32_t); + outbuf = malloc(bufsize); + if (!outbuf) + goto done; + + *keyb_data = (uint8_t *)outbuf; + *keyb_size = bufsize; + + *outbuf++ = nwords; + + /* Initialize BIGNUMs */ +#define NEW_BIGNUM(x) do { x = BN_new(); if (!x) goto done; } while (0) + NEW_BIGNUM(N); + NEW_BIGNUM(Big1); + NEW_BIGNUM(Big2); + NEW_BIGNUM(Big32); + NEW_BIGNUM(BigMinus1); + NEW_BIGNUM(N0inv); + NEW_BIGNUM(R); + NEW_BIGNUM(RR); + NEW_BIGNUM(RRTemp); + NEW_BIGNUM(NnumBits); + NEW_BIGNUM(n); + NEW_BIGNUM(rr); + NEW_BIGNUM(B); +#undef NEW_BIGNUM + + BN_copy(N, rsa_private_key->n); + BN_set_word(Big1, 1L); + BN_set_word(Big2, 2L); + BN_set_word(Big32, 32L); + BN_sub(BigMinus1, Big1, Big2); + + BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */ + + /* Calculate and output N0inv = -1 / N[0] mod 2^32 */ + BN_mod_inverse(N0inv, N, B, bn_ctx); + BN_sub(N0inv, B, N0inv); + n0invout = BN_get_word(N0inv); + + *outbuf++ = n0invout; + + /* Calculate R = 2^(# of key bits) */ + BN_set_word(NnumBits, BN_num_bits(N)); + BN_exp(R, Big2, NnumBits, bn_ctx); + + /* Calculate RR = R^2 mod N */ + BN_copy(RR, R); + BN_mul(RRTemp, RR, R, bn_ctx); + BN_mod(RR, RRTemp, N, bn_ctx); + + + /* Write out modulus as little endian array of integers. */ + for (i = 0; i < nwords; ++i) { + uint32_t nout; + + BN_mod(n, N, B, bn_ctx); /* n = N mod B */ + nout = BN_get_word(n); + *outbuf++ = nout; + + BN_rshift(N, N, 32); /* N = N/B */ + } + + /* Write R^2 as little endian array of integers. */ + for (i = 0; i < nwords; ++i) { + uint32_t rrout; + + BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */ + rrout = BN_get_word(rr); + *outbuf++ = rrout; + + BN_rshift(RR, RR, 32); /* RR = RR/B */ + } + + outbuf = NULL; + retval = 0; + +done: + free(outbuf); + /* Free BIGNUMs. */ + BN_free(Big1); + BN_free(Big2); + BN_free(Big32); + BN_free(BigMinus1); + BN_free(N0inv); + BN_free(R); + BN_free(RRTemp); + BN_free(NnumBits); + BN_free(n); + BN_free(rr); + + return retval; } |