summaryrefslogtreecommitdiff
path: root/host/lib/util_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/util_misc.c')
-rw-r--r--host/lib/util_misc.c133
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;
}