"Fossies" - the Fresh Open Source Software Archive

Member "openssl-1.1.1g/crypto/rand/drbg_ctr.c" (21 Apr 2020, 12723 Bytes) of package /linux/misc/openssl-1.1.1g.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "drbg_ctr.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.1.1f_vs_1.1.1g.

    1 /*
    2  * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
    3  *
    4  * Licensed under the OpenSSL license (the "License").  You may not use
    5  * this file except in compliance with the License.  You can obtain a copy
    6  * in the file LICENSE in the source distribution or at
    7  * https://www.openssl.org/source/license.html
    8  */
    9 
   10 #include <stdlib.h>
   11 #include <string.h>
   12 #include <openssl/crypto.h>
   13 #include <openssl/err.h>
   14 #include <openssl/rand.h>
   15 #include "modes_local.h"
   16 #include "internal/thread_once.h"
   17 #include "rand_local.h"
   18 
   19 /*
   20  * Implementation of NIST SP 800-90A CTR DRBG.
   21  */
   22 
   23 static void inc_128(RAND_DRBG_CTR *ctr)
   24 {
   25     unsigned char *p = &ctr->V[0];
   26     u32 n = 16, c = 1;
   27 
   28     do {
   29         --n;
   30         c += p[n];
   31         p[n] = (u8)c;
   32         c >>= 8;
   33     } while (n);
   34 }
   35 
   36 static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
   37 {
   38     size_t i, n;
   39 
   40     if (in == NULL || inlen == 0)
   41         return;
   42 
   43     /*
   44      * Any zero padding will have no effect on the result as we
   45      * are XORing. So just process however much input we have.
   46      */
   47     n = inlen < ctr->keylen ? inlen : ctr->keylen;
   48     for (i = 0; i < n; i++)
   49         ctr->K[i] ^= in[i];
   50     if (inlen <= ctr->keylen)
   51         return;
   52 
   53     n = inlen - ctr->keylen;
   54     if (n > 16) {
   55         /* Should never happen */
   56         n = 16;
   57     }
   58     for (i = 0; i < n; i++)
   59         ctr->V[i] ^= in[i + ctr->keylen];
   60 }
   61 
   62 /*
   63  * Process a complete block using BCC algorithm of SP 800-90A 10.3.3
   64  */
   65 __owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out,
   66                                 const unsigned char *in)
   67 {
   68     int i, outlen = AES_BLOCK_SIZE;
   69 
   70     for (i = 0; i < 16; i++)
   71         out[i] ^= in[i];
   72 
   73     if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, AES_BLOCK_SIZE)
   74         || outlen != AES_BLOCK_SIZE)
   75         return 0;
   76     return 1;
   77 }
   78 
   79 
   80 /*
   81  * Handle several BCC operations for as much data as we need for K and X
   82  */
   83 __owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in)
   84 {
   85     if (!ctr_BCC_block(ctr, ctr->KX, in)
   86         || !ctr_BCC_block(ctr, ctr->KX + 16, in))
   87         return 0;
   88     if (ctr->keylen != 16 && !ctr_BCC_block(ctr, ctr->KX + 32, in))
   89         return 0;
   90     return 1;
   91 }
   92 
   93 /*
   94  * Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
   95  * see 10.3.1 stage 7.
   96  */
   97 __owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr)
   98 {
   99     memset(ctr->KX, 0, 48);
  100     memset(ctr->bltmp, 0, 16);
  101     if (!ctr_BCC_block(ctr, ctr->KX, ctr->bltmp))
  102         return 0;
  103     ctr->bltmp[3] = 1;
  104     if (!ctr_BCC_block(ctr, ctr->KX + 16, ctr->bltmp))
  105         return 0;
  106     if (ctr->keylen != 16) {
  107         ctr->bltmp[3] = 2;
  108         if (!ctr_BCC_block(ctr, ctr->KX + 32, ctr->bltmp))
  109             return 0;
  110     }
  111     return 1;
  112 }
  113 
  114 /*
  115  * Process several blocks into BCC algorithm, some possibly partial
  116  */
  117 __owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr,
  118                                  const unsigned char *in, size_t inlen)
  119 {
  120     if (in == NULL || inlen == 0)
  121         return 1;
  122 
  123     /* If we have partial block handle it first */
  124     if (ctr->bltmp_pos) {
  125         size_t left = 16 - ctr->bltmp_pos;
  126 
  127         /* If we now have a complete block process it */
  128         if (inlen >= left) {
  129             memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
  130             if (!ctr_BCC_blocks(ctr, ctr->bltmp))
  131                 return 0;
  132             ctr->bltmp_pos = 0;
  133             inlen -= left;
  134             in += left;
  135         }
  136     }
  137 
  138     /* Process zero or more complete blocks */
  139     for (; inlen >= 16; in += 16, inlen -= 16) {
  140         if (!ctr_BCC_blocks(ctr, in))
  141             return 0;
  142     }
  143 
  144     /* Copy any remaining partial block to the temporary buffer */
  145     if (inlen > 0) {
  146         memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
  147         ctr->bltmp_pos += inlen;
  148     }
  149     return 1;
  150 }
  151 
  152 __owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr)
  153 {
  154     if (ctr->bltmp_pos) {
  155         memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
  156         if (!ctr_BCC_blocks(ctr, ctr->bltmp))
  157             return 0;
  158     }
  159     return 1;
  160 }
  161 
  162 __owur static int ctr_df(RAND_DRBG_CTR *ctr,
  163                          const unsigned char *in1, size_t in1len,
  164                          const unsigned char *in2, size_t in2len,
  165                          const unsigned char *in3, size_t in3len)
  166 {
  167     static unsigned char c80 = 0x80;
  168     size_t inlen;
  169     unsigned char *p = ctr->bltmp;
  170     int outlen = AES_BLOCK_SIZE;
  171 
  172     if (!ctr_BCC_init(ctr))
  173         return 0;
  174     if (in1 == NULL)
  175         in1len = 0;
  176     if (in2 == NULL)
  177         in2len = 0;
  178     if (in3 == NULL)
  179         in3len = 0;
  180     inlen = in1len + in2len + in3len;
  181     /* Initialise L||N in temporary block */
  182     *p++ = (inlen >> 24) & 0xff;
  183     *p++ = (inlen >> 16) & 0xff;
  184     *p++ = (inlen >> 8) & 0xff;
  185     *p++ = inlen & 0xff;
  186 
  187     /* NB keylen is at most 32 bytes */
  188     *p++ = 0;
  189     *p++ = 0;
  190     *p++ = 0;
  191     *p = (unsigned char)((ctr->keylen + 16) & 0xff);
  192     ctr->bltmp_pos = 8;
  193     if (!ctr_BCC_update(ctr, in1, in1len)
  194         || !ctr_BCC_update(ctr, in2, in2len)
  195         || !ctr_BCC_update(ctr, in3, in3len)
  196         || !ctr_BCC_update(ctr, &c80, 1)
  197         || !ctr_BCC_final(ctr))
  198         return 0;
  199     /* Set up key K */
  200     if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->KX, NULL, 1))
  201         return 0;
  202     /* X follows key K */
  203     if (!EVP_CipherUpdate(ctr->ctx, ctr->KX, &outlen, ctr->KX + ctr->keylen,
  204                           AES_BLOCK_SIZE)
  205         || outlen != AES_BLOCK_SIZE)
  206         return 0;
  207     if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 16, &outlen, ctr->KX,
  208                           AES_BLOCK_SIZE)
  209         || outlen != AES_BLOCK_SIZE)
  210         return 0;
  211     if (ctr->keylen != 16)
  212         if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 32, &outlen, ctr->KX + 16,
  213                               AES_BLOCK_SIZE)
  214             || outlen != AES_BLOCK_SIZE)
  215             return 0;
  216     return 1;
  217 }
  218 
  219 /*
  220  * NB the no-df Update in SP800-90A specifies a constant input length
  221  * of seedlen, however other uses of this algorithm pad the input with
  222  * zeroes if necessary and have up to two parameters XORed together,
  223  * so we handle both cases in this function instead.
  224  */
  225 __owur static int ctr_update(RAND_DRBG *drbg,
  226                              const unsigned char *in1, size_t in1len,
  227                              const unsigned char *in2, size_t in2len,
  228                              const unsigned char *nonce, size_t noncelen)
  229 {
  230     RAND_DRBG_CTR *ctr = &drbg->data.ctr;
  231     int outlen = AES_BLOCK_SIZE;
  232 
  233     /* correct key is already set up. */
  234     inc_128(ctr);
  235     if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outlen, ctr->V, AES_BLOCK_SIZE)
  236         || outlen != AES_BLOCK_SIZE)
  237         return 0;
  238 
  239     /* If keylen longer than 128 bits need extra encrypt */
  240     if (ctr->keylen != 16) {
  241         inc_128(ctr);
  242         if (!EVP_CipherUpdate(ctr->ctx, ctr->K+16, &outlen, ctr->V,
  243                               AES_BLOCK_SIZE)
  244             || outlen != AES_BLOCK_SIZE)
  245             return 0;
  246     }
  247     inc_128(ctr);
  248     if (!EVP_CipherUpdate(ctr->ctx, ctr->V, &outlen, ctr->V, AES_BLOCK_SIZE)
  249         || outlen != AES_BLOCK_SIZE)
  250         return 0;
  251 
  252     /* If 192 bit key part of V is on end of K */
  253     if (ctr->keylen == 24) {
  254         memcpy(ctr->V + 8, ctr->V, 8);
  255         memcpy(ctr->V, ctr->K + 24, 8);
  256     }
  257 
  258     if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
  259         /* If no input reuse existing derived value */
  260         if (in1 != NULL || nonce != NULL || in2 != NULL)
  261             if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
  262                 return 0;
  263         /* If this a reuse input in1len != 0 */
  264         if (in1len)
  265             ctr_XOR(ctr, ctr->KX, drbg->seedlen);
  266     } else {
  267         ctr_XOR(ctr, in1, in1len);
  268         ctr_XOR(ctr, in2, in2len);
  269     }
  270 
  271     if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1))
  272         return 0;
  273     return 1;
  274 }
  275 
  276 __owur static int drbg_ctr_instantiate(RAND_DRBG *drbg,
  277                                        const unsigned char *entropy, size_t entropylen,
  278                                        const unsigned char *nonce, size_t noncelen,
  279                                        const unsigned char *pers, size_t perslen)
  280 {
  281     RAND_DRBG_CTR *ctr = &drbg->data.ctr;
  282 
  283     if (entropy == NULL)
  284         return 0;
  285 
  286     memset(ctr->K, 0, sizeof(ctr->K));
  287     memset(ctr->V, 0, sizeof(ctr->V));
  288     if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1))
  289         return 0;
  290     if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))
  291         return 0;
  292     return 1;
  293 }
  294 
  295 __owur static int drbg_ctr_reseed(RAND_DRBG *drbg,
  296                                   const unsigned char *entropy, size_t entropylen,
  297                                   const unsigned char *adin, size_t adinlen)
  298 {
  299     if (entropy == NULL)
  300         return 0;
  301     if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
  302         return 0;
  303     return 1;
  304 }
  305 
  306 __owur static int drbg_ctr_generate(RAND_DRBG *drbg,
  307                                     unsigned char *out, size_t outlen,
  308                                     const unsigned char *adin, size_t adinlen)
  309 {
  310     RAND_DRBG_CTR *ctr = &drbg->data.ctr;
  311 
  312     if (adin != NULL && adinlen != 0) {
  313         if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
  314             return 0;
  315         /* This means we reuse derived value */
  316         if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
  317             adin = NULL;
  318             adinlen = 1;
  319         }
  320     } else {
  321         adinlen = 0;
  322     }
  323 
  324     for ( ; ; ) {
  325         int outl = AES_BLOCK_SIZE;
  326 
  327         inc_128(ctr);
  328         if (outlen < 16) {
  329             /* Use K as temp space as it will be updated */
  330             if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outl, ctr->V,
  331                                   AES_BLOCK_SIZE)
  332                 || outl != AES_BLOCK_SIZE)
  333                 return 0;
  334             memcpy(out, ctr->K, outlen);
  335             break;
  336         }
  337         if (!EVP_CipherUpdate(ctr->ctx, out, &outl, ctr->V, AES_BLOCK_SIZE)
  338             || outl != AES_BLOCK_SIZE)
  339             return 0;
  340         out += 16;
  341         outlen -= 16;
  342         if (outlen == 0)
  343             break;
  344     }
  345 
  346     if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
  347         return 0;
  348     return 1;
  349 }
  350 
  351 static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
  352 {
  353     EVP_CIPHER_CTX_free(drbg->data.ctr.ctx);
  354     EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
  355     OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
  356     return 1;
  357 }
  358 
  359 static RAND_DRBG_METHOD drbg_ctr_meth = {
  360     drbg_ctr_instantiate,
  361     drbg_ctr_reseed,
  362     drbg_ctr_generate,
  363     drbg_ctr_uninstantiate
  364 };
  365 
  366 int drbg_ctr_init(RAND_DRBG *drbg)
  367 {
  368     RAND_DRBG_CTR *ctr = &drbg->data.ctr;
  369     size_t keylen;
  370 
  371     switch (drbg->type) {
  372     default:
  373         /* This can't happen, but silence the compiler warning. */
  374         return 0;
  375     case NID_aes_128_ctr:
  376         keylen = 16;
  377         ctr->cipher = EVP_aes_128_ecb();
  378         break;
  379     case NID_aes_192_ctr:
  380         keylen = 24;
  381         ctr->cipher = EVP_aes_192_ecb();
  382         break;
  383     case NID_aes_256_ctr:
  384         keylen = 32;
  385         ctr->cipher = EVP_aes_256_ecb();
  386         break;
  387     }
  388 
  389     drbg->meth = &drbg_ctr_meth;
  390 
  391     ctr->keylen = keylen;
  392     if (ctr->ctx == NULL)
  393         ctr->ctx = EVP_CIPHER_CTX_new();
  394     if (ctr->ctx == NULL)
  395         return 0;
  396     drbg->strength = keylen * 8;
  397     drbg->seedlen = keylen + 16;
  398 
  399     if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
  400         /* df initialisation */
  401         static const unsigned char df_key[32] = {
  402             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  403             0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  404             0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  405             0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
  406         };
  407 
  408         if (ctr->ctx_df == NULL)
  409             ctr->ctx_df = EVP_CIPHER_CTX_new();
  410         if (ctr->ctx_df == NULL)
  411             return 0;
  412         /* Set key schedule for df_key */
  413         if (!EVP_CipherInit_ex(ctr->ctx_df, ctr->cipher, NULL, df_key, NULL, 1))
  414             return 0;
  415 
  416         drbg->min_entropylen = ctr->keylen;
  417         drbg->max_entropylen = DRBG_MAX_LENGTH;
  418         drbg->min_noncelen = drbg->min_entropylen / 2;
  419         drbg->max_noncelen = DRBG_MAX_LENGTH;
  420         drbg->max_perslen = DRBG_MAX_LENGTH;
  421         drbg->max_adinlen = DRBG_MAX_LENGTH;
  422     } else {
  423         drbg->min_entropylen = drbg->seedlen;
  424         drbg->max_entropylen = drbg->seedlen;
  425         /* Nonce not used */
  426         drbg->min_noncelen = 0;
  427         drbg->max_noncelen = 0;
  428         drbg->max_perslen = drbg->seedlen;
  429         drbg->max_adinlen = drbg->seedlen;
  430     }
  431 
  432     drbg->max_request = 1 << 16;
  433 
  434     return 1;
  435 }