Home | History | Annotate | Download | only in rand
      1 /* Copyright (c) 2017, Google Inc.
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     14 
     15 #include <openssl/rand.h>
     16 
     17 #include <openssl/type_check.h>
     18 #include <openssl/mem.h>
     19 
     20 #include "internal.h"
     21 #include "../cipher/internal.h"
     22 
     23 
     24 /* Section references in this file refer to SP 800-90Ar1:
     25  * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf */
     26 
     27 /* See table 3. */
     28 static const uint64_t kMaxReseedCount = UINT64_C(1) << 48;
     29 
     30 int CTR_DRBG_init(CTR_DRBG_STATE *drbg,
     31                   const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
     32                   const uint8_t *personalization, size_t personalization_len) {
     33   /* Section 10.2.1.3.1 */
     34   if (personalization_len > CTR_DRBG_ENTROPY_LEN) {
     35     return 0;
     36   }
     37 
     38   uint8_t seed_material[CTR_DRBG_ENTROPY_LEN];
     39   OPENSSL_memcpy(seed_material, entropy, CTR_DRBG_ENTROPY_LEN);
     40 
     41   for (size_t i = 0; i < personalization_len; i++) {
     42     seed_material[i] ^= personalization[i];
     43   }
     44 
     45   /* Section 10.2.1.2 */
     46 
     47   /* kInitMask is the result of encrypting blocks with big-endian value 1, 2
     48    * and 3 with the all-zero AES-256 key. */
     49   static const uint8_t kInitMask[CTR_DRBG_ENTROPY_LEN] = {
     50       0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1,
     51       0xc4, 0xcb, 0x73, 0x8b, 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
     52       0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18, 0x72, 0x60, 0x03, 0xca,
     53       0x37, 0xa6, 0x2a, 0x74, 0xd1, 0xa2, 0xf5, 0x8e, 0x75, 0x06, 0x35, 0x8e,
     54   };
     55 
     56   for (size_t i = 0; i < sizeof(kInitMask); i++) {
     57     seed_material[i] ^= kInitMask[i];
     58   }
     59 
     60   drbg->ctr = aes_ctr_set_key(&drbg->ks, NULL, &drbg->block, seed_material, 32);
     61   OPENSSL_memcpy(drbg->counter.bytes, seed_material + 32, 16);
     62   drbg->reseed_counter = 1;
     63 
     64   return 1;
     65 }
     66 
     67 OPENSSL_COMPILE_ASSERT(CTR_DRBG_ENTROPY_LEN % AES_BLOCK_SIZE == 0,
     68                        not_a_multiple_of_block_size);
     69 
     70 /* ctr_inc adds |n| to the last four bytes of |drbg->counter|, treated as a
     71  * big-endian number. */
     72 static void ctr32_add(CTR_DRBG_STATE *drbg, uint32_t n) {
     73   drbg->counter.words[3] =
     74       CRYPTO_bswap4(CRYPTO_bswap4(drbg->counter.words[3]) + n);
     75 }
     76 
     77 static int CTR_DRBG_update(CTR_DRBG_STATE *drbg, const uint8_t *data,
     78                            size_t data_len) {
     79   /* Section 10.2.1.2. A value of |data_len| which less than
     80    * |CTR_DRBG_ENTROPY_LEN| is permitted and acts the same as right-padding
     81    * with zeros. This can save a copy. */
     82   if (data_len > CTR_DRBG_ENTROPY_LEN) {
     83     return 0;
     84   }
     85 
     86   uint8_t temp[CTR_DRBG_ENTROPY_LEN];
     87   for (size_t i = 0; i < CTR_DRBG_ENTROPY_LEN; i += AES_BLOCK_SIZE) {
     88     ctr32_add(drbg, 1);
     89     drbg->block(drbg->counter.bytes, temp + i, &drbg->ks);
     90   }
     91 
     92   for (size_t i = 0; i < data_len; i++) {
     93     temp[i] ^= data[i];
     94   }
     95 
     96   drbg->ctr = aes_ctr_set_key(&drbg->ks, NULL, &drbg->block, temp, 32);
     97   OPENSSL_memcpy(drbg->counter.bytes, temp + 32, 16);
     98 
     99   return 1;
    100 }
    101 
    102 int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg,
    103                     const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
    104                     const uint8_t *additional_data,
    105                     size_t additional_data_len) {
    106   /* Section 10.2.1.4 */
    107   uint8_t entropy_copy[CTR_DRBG_ENTROPY_LEN];
    108 
    109   if (additional_data_len > 0) {
    110     if (additional_data_len > CTR_DRBG_ENTROPY_LEN) {
    111       return 0;
    112     }
    113 
    114     OPENSSL_memcpy(entropy_copy, entropy, CTR_DRBG_ENTROPY_LEN);
    115     for (size_t i = 0; i < additional_data_len; i++) {
    116       entropy_copy[i] ^= additional_data[i];
    117     }
    118 
    119     entropy = entropy_copy;
    120   }
    121 
    122   if (!CTR_DRBG_update(drbg, entropy, CTR_DRBG_ENTROPY_LEN)) {
    123     return 0;
    124   }
    125 
    126   drbg->reseed_counter = 1;
    127 
    128   return 1;
    129 }
    130 
    131 int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, size_t out_len,
    132                       const uint8_t *additional_data,
    133                       size_t additional_data_len) {
    134   /* See 9.3.1 */
    135   if (out_len > CTR_DRBG_MAX_GENERATE_LENGTH) {
    136     return 0;
    137   }
    138 
    139   /* See 10.2.1.5.1 */
    140   if (drbg->reseed_counter > kMaxReseedCount) {
    141     return 0;
    142   }
    143 
    144   if (additional_data_len != 0 &&
    145       !CTR_DRBG_update(drbg, additional_data, additional_data_len)) {
    146     return 0;
    147   }
    148 
    149   /* kChunkSize is used to interact better with the cache. Since the AES-CTR
    150    * code assumes that it's encrypting rather than just writing keystream, the
    151    * buffer has to be zeroed first. Without chunking, large reads would zero
    152    * the whole buffer, flushing the L1 cache, and then do another pass (missing
    153    * the cache every time) to encrypt it. The code can avoid this by
    154    * chunking. */
    155   static const size_t kChunkSize = 8 * 1024;
    156 
    157   while (out_len >= AES_BLOCK_SIZE) {
    158     size_t todo = kChunkSize;
    159     if (todo > out_len) {
    160       todo = out_len;
    161     }
    162 
    163     todo &= ~(AES_BLOCK_SIZE-1);
    164     const size_t num_blocks = todo / AES_BLOCK_SIZE;
    165 
    166     if (drbg->ctr) {
    167       OPENSSL_memset(out, 0, todo);
    168       ctr32_add(drbg, 1);
    169       drbg->ctr(out, out, num_blocks, &drbg->ks, drbg->counter.bytes);
    170       ctr32_add(drbg, num_blocks - 1);
    171     } else {
    172       for (size_t i = 0; i < todo; i += AES_BLOCK_SIZE) {
    173         ctr32_add(drbg, 1);
    174         drbg->block(drbg->counter.bytes, out + i, &drbg->ks);
    175       }
    176     }
    177 
    178     out += todo;
    179     out_len -= todo;
    180   }
    181 
    182   if (out_len > 0) {
    183     uint8_t block[AES_BLOCK_SIZE];
    184     ctr32_add(drbg, 1);
    185     drbg->block(drbg->counter.bytes, block, &drbg->ks);
    186 
    187     OPENSSL_memcpy(out, block, out_len);
    188   }
    189 
    190   if (!CTR_DRBG_update(drbg, additional_data, additional_data_len)) {
    191     return 0;
    192   }
    193 
    194   drbg->reseed_counter++;
    195   return 1;
    196 }
    197 
    198 void CTR_DRBG_clear(CTR_DRBG_STATE *drbg) {
    199   OPENSSL_cleanse(drbg, sizeof(CTR_DRBG_STATE));
    200 }
    201