You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
3.1 KiB
144 lines
3.1 KiB
/* 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.
|
|
*
|
|
* Miscellaneous functions for userspace vboot utilities.
|
|
*/
|
|
|
|
#include <openssl/bn.h>
|
|
#include <openssl/rsa.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "cryptolib.h"
|
|
#include "host_common.h"
|
|
#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);
|
|
}
|
|
|
|
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;
|
|
}
|