Home | History | Annotate | Download | only in cryptolib
      1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  *
      5  * Implementation of RSA utility functions.
      6  */
      7 
      8 #include "sysincludes.h"
      9 
     10 #include "cryptolib.h"
     11 #include "stateful_util.h"
     12 #include "utility.h"
     13 #include "vboot_api.h"
     14 
     15 uint64_t RSAProcessedKeySize(uint64_t algorithm, uint64_t* out_size) {
     16   int key_len; /* Key length in bytes.  (int type matches siglen_map) */
     17   if (algorithm < kNumAlgorithms) {
     18     key_len = siglen_map[algorithm];
     19     /* Total size needed by a RSAPublicKey buffer is =
     20      *  2 * key_len bytes for the  n and rr arrays
     21      *  + sizeof len + sizeof n0inv.
     22      */
     23     *out_size = (2 * key_len + sizeof(uint32_t) + sizeof(uint32_t));
     24     return 1;
     25   }
     26   return 0;
     27 }
     28 
     29 RSAPublicKey* RSAPublicKeyNew(void) {
     30   RSAPublicKey* key = (RSAPublicKey*) VbExMalloc(sizeof(RSAPublicKey));
     31   key->n = NULL;
     32   key->rr = NULL;
     33   key->len = 0;
     34   key->algorithm = kNumAlgorithms;
     35   return key;
     36 }
     37 
     38 void RSAPublicKeyFree(RSAPublicKey* key) {
     39   if (key) {
     40     if (key->n)
     41       VbExFree(key->n);
     42     if (key->rr)
     43       VbExFree(key->rr);
     44     VbExFree(key);
     45   }
     46 }
     47 
     48 RSAPublicKey* RSAPublicKeyFromBuf(const uint8_t* buf, uint64_t len) {
     49   RSAPublicKey* key = RSAPublicKeyNew();
     50   MemcpyState st;
     51   uint64_t key_len;
     52 
     53   StatefulInit(&st, (void*)buf, len);
     54 
     55   StatefulMemcpy(&st, &key->len, sizeof(key->len));
     56   /* key length in bytes (avoiding possible 32-bit rollover) */
     57   key_len = key->len;
     58   key_len *= sizeof(uint32_t);
     59 
     60   /* Sanity Check the key length. */
     61   if (RSA1024NUMBYTES != key_len &&
     62       RSA2048NUMBYTES != key_len &&
     63       RSA4096NUMBYTES != key_len &&
     64       RSA8192NUMBYTES != key_len) {
     65     RSAPublicKeyFree(key);
     66     return NULL;
     67   }
     68 
     69   key->n = (uint32_t*) VbExMalloc(key_len);
     70   key->rr = (uint32_t*) VbExMalloc(key_len);
     71 
     72   StatefulMemcpy(&st, &key->n0inv, sizeof(key->n0inv));
     73   StatefulMemcpy(&st, key->n, key_len);
     74   StatefulMemcpy(&st, key->rr, key_len);
     75   if (st.overrun || st.remaining_len != 0) {  /* Underrun or overrun. */
     76     RSAPublicKeyFree(key);
     77     return NULL;
     78   }
     79 
     80   return key;
     81 }
     82 
     83 int RSAVerifyBinary_f(const uint8_t* key_blob,
     84                       const RSAPublicKey* key,
     85                       const uint8_t* buf,
     86                       uint64_t len,
     87                       const uint8_t* sig,
     88                       unsigned int algorithm) {
     89   RSAPublicKey* verification_key = NULL;
     90   uint8_t* digest = NULL;
     91   uint64_t key_size;
     92   int sig_size;
     93   int success;
     94 
     95   if (algorithm >= (unsigned int)kNumAlgorithms)
     96     return 0;  /* Invalid algorithm. */
     97   if (!RSAProcessedKeySize(algorithm, &key_size))
     98     return 0;
     99   sig_size = siglen_map[algorithm];
    100 
    101   if (key_blob && !key)
    102     verification_key = RSAPublicKeyFromBuf(key_blob, key_size);
    103   else if (!key_blob && key)
    104     verification_key = (RSAPublicKey*) key;  /* Supress const warning. */
    105   else
    106     return 0; /* Both can't be NULL or non-NULL. */
    107 
    108   /* Ensure we have a valid key. */
    109   if (!verification_key)
    110     return 0;
    111 
    112   digest = DigestBuf(buf, len, algorithm);
    113   success = RSAVerify(verification_key, sig, (uint32_t)sig_size,
    114                       (uint8_t)algorithm, digest);
    115 
    116   VbExFree(digest);
    117   if (!key)
    118     RSAPublicKeyFree(verification_key);  /* Only free if we allocated it. */
    119   return success;
    120 }
    121 
    122 /* Version of RSAVerifyBinary_f() where instead of the raw binary blob
    123  * of data, its digest is passed as the argument. */
    124 int RSAVerifyBinaryWithDigest_f(const uint8_t* key_blob,
    125                                 const RSAPublicKey* key,
    126                                 const uint8_t* digest,
    127                                 const uint8_t* sig,
    128                                 unsigned int algorithm) {
    129   RSAPublicKey* verification_key = NULL;
    130   uint64_t key_size;
    131   int sig_size;
    132   int success;
    133 
    134   if (algorithm >= (unsigned int)kNumAlgorithms)
    135     return 0;  /* Invalid algorithm. */
    136   if (!RSAProcessedKeySize(algorithm, &key_size))
    137     return 0;
    138   sig_size = siglen_map[algorithm];
    139 
    140   if (key_blob && !key)
    141     verification_key = RSAPublicKeyFromBuf(key_blob, key_size);
    142   else if (!key_blob && key)
    143     verification_key = (RSAPublicKey*) key;  /* Supress const warning. */
    144   else
    145     return 0; /* Both can't be NULL or non-NULL. */
    146 
    147   /* Ensure we have a valid key. */
    148   if (!verification_key)
    149     return 0;
    150 
    151   success = RSAVerify(verification_key, sig, (uint32_t)sig_size,
    152                       (uint8_t)algorithm, digest);
    153 
    154   if (!key)
    155     RSAPublicKeyFree(verification_key);  /* Only free if we allocated it. */
    156   return success;
    157 }
    158