Add error for health check failure.
[openssl.git] / fips / rand / fips_drbg_ctr.c
1 /* fips/rand/fips_drbg_ctr.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53
54 #include <stdlib.h>
55 #include <string.h>
56 #include <openssl/crypto.h>
57 #include <openssl/evp.h>
58 #include <openssl/aes.h>
59 #include <openssl/fips.h>
60 #include <openssl/fips_rand.h>
61 #include "fips_rand_lcl.h"
62
63 static void inc_128(DRBG_CTR_CTX *cctx)
64         {
65         int i;
66         unsigned char c;
67         unsigned char *p = cctx->V + 15;
68         for (i = 0; i < 16; i++)
69                 {
70                 c = *p;
71                 c++;
72                 *p = c;
73                 if (c)
74                         return;
75                 p--;
76                 }
77         }
78
79 static void ctr_XOR(DRBG_CTR_CTX *cctx, const unsigned char *in, size_t inlen)
80         {
81         size_t i, n;
82         /* Any zero padding will have no effect on the result as we
83          * are XORing. So just process however much input we have.
84          */
85
86         if (!in || !inlen)
87                 return;
88
89         if (inlen < cctx->keylen)
90                 n = inlen;
91         else
92                 n = cctx->keylen;
93
94         for (i = 0; i < n; i++)
95                 cctx->K[i] ^= in[i];
96         if (inlen <= cctx->keylen)
97                 return;
98
99         n = inlen - cctx->keylen;
100         /* Should never happen */
101         if (n > 16)
102                 n = 16;
103         for (i = 0; i < 16; i++)
104                 cctx->V[i] ^= in[i + cctx->keylen];
105         }
106
107 /* Process a complete block using BCC algorithm of SPP 800-90 10.4.3 */
108
109 static void ctr_BCC_block(DRBG_CTR_CTX *cctx, unsigned char *out,
110                                 const unsigned char *in)
111         {
112         int i;
113         for (i = 0; i < 16; i++)
114                 out[i] ^= in[i];
115         AES_encrypt(out, out, &cctx->df_ks);
116 #if 0
117 fprintf(stderr, "BCC in+out\n");
118 BIO_dump_fp(stderr, in, 16);
119 BIO_dump_fp(stderr, out, 16);
120 #endif
121         }
122
123 /* Handle several BCC operations for as much data as we need for K and X */
124 static void ctr_BCC_blocks(DRBG_CTR_CTX *cctx, const unsigned char *in)
125         {
126         ctr_BCC_block(cctx, cctx->KX, in);
127         ctr_BCC_block(cctx, cctx->KX + 16, in);
128         if (cctx->keylen != 16)
129                 ctr_BCC_block(cctx, cctx->KX + 32, in);
130         }
131 /* Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
132  * see 10.4.2 stage 7.
133  */
134 static void ctr_BCC_init(DRBG_CTR_CTX *cctx)
135         {
136         memset(cctx->KX, 0, 48);
137         memset(cctx->bltmp, 0, 16);
138         ctr_BCC_block(cctx, cctx->KX, cctx->bltmp);
139         cctx->bltmp[3] = 1;
140         ctr_BCC_block(cctx, cctx->KX + 16, cctx->bltmp);
141         if (cctx->keylen != 16)
142                 {
143                 cctx->bltmp[3] = 2;
144                 ctr_BCC_block(cctx, cctx->KX + 32, cctx->bltmp);
145                 }
146         }
147
148 /* Process several blocks into BCC algorithm, some possibly partial */
149 static void ctr_BCC_update(DRBG_CTR_CTX *cctx,
150                                 const unsigned char *in, size_t inlen)
151         {
152         if (!in || !inlen)
153                 return;
154         /* If we have partial block handle it first */
155         if (cctx->bltmp_pos)
156                 {
157                 size_t left = 16 - cctx->bltmp_pos;
158                 /* If we now have a complete block process it */
159                 if (inlen >= left)
160                         {
161                         memcpy(cctx->bltmp + cctx->bltmp_pos, in, left);
162                         ctr_BCC_blocks(cctx, cctx->bltmp);
163                         cctx->bltmp_pos = 0;
164                         inlen -= left;
165                         in += left;
166                         }
167                 }
168         /* Process zero or more complete blocks */
169         while (inlen >= 16)
170                 {
171                 ctr_BCC_blocks(cctx, in);
172                 in += 16;
173                 inlen -= 16;
174                 }
175         /* Copy any remaining partial block to the temporary buffer */
176         if (inlen > 0)
177                 {
178                 memcpy(cctx->bltmp + cctx->bltmp_pos, in, inlen);
179                 cctx->bltmp_pos += inlen;
180                 }
181         }
182
183 static void ctr_BCC_final(DRBG_CTR_CTX *cctx)
184         {
185         if (cctx->bltmp_pos)
186                 {
187                 memset(cctx->bltmp + cctx->bltmp_pos, 0, 16 - cctx->bltmp_pos);
188                 ctr_BCC_blocks(cctx, cctx->bltmp);
189                 }
190         }
191
192 static void ctr_df(DRBG_CTR_CTX *cctx,
193                         const unsigned char *in1, size_t in1len,
194                         const unsigned char *in2, size_t in2len,
195                         const unsigned char *in3, size_t in3len)
196         {
197         size_t inlen;
198         unsigned char *p = cctx->bltmp;
199         static unsigned char c80 = 0x80;
200
201         ctr_BCC_init(cctx);
202         if (!in1)
203                 in1len = 0;
204         if (!in2)
205                 in2len = 0;
206         if (!in3)
207                 in3len = 0;
208         inlen = in1len + in2len + in3len;
209         /* Initialise L||N in temporary block */
210         *p++ = (inlen >> 24) & 0xff;
211         *p++ = (inlen >> 16) & 0xff;
212         *p++ = (inlen >> 8) & 0xff;
213         *p++ = inlen & 0xff;
214         /* NB keylen is at most 32 bytes */
215         *p++ = 0;
216         *p++ = 0;
217         *p++ = 0;
218         *p = (unsigned char)((cctx->keylen + 16) & 0xff);
219         cctx->bltmp_pos = 8;
220         ctr_BCC_update(cctx, in1, in1len);
221         ctr_BCC_update(cctx, in2, in2len);
222         ctr_BCC_update(cctx, in3, in3len);
223         ctr_BCC_update(cctx, &c80, 1);
224         ctr_BCC_final(cctx);
225         /* Set up key K */
226         AES_set_encrypt_key(cctx->KX, cctx->keylen * 8, &cctx->df_kxks);
227         /* X follows key K */
228         AES_encrypt(cctx->KX + cctx->keylen, cctx->KX, &cctx->df_kxks);
229         AES_encrypt(cctx->KX, cctx->KX + 16, &cctx->df_kxks);
230         if (cctx->keylen != 16)
231                 AES_encrypt(cctx->KX + 16, cctx->KX + 32, &cctx->df_kxks);
232 #if 0
233 fprintf(stderr, "Output of ctr_df:\n");
234 BIO_dump_fp(stderr, cctx->KX, cctx->keylen + 16);
235 #endif
236         }
237
238 /* NB the no-df  Update in SP800-90 specifies a constant input length
239  * of seedlen, however other uses of this algorithm pad the input with
240  * zeroes if necessary and have up to two parameters XORed together,
241  * handle both cases in this function instead.
242  */
243
244 static void ctr_Update(DRBG_CTX *dctx,
245                 const unsigned char *in1, size_t in1len,
246                 const unsigned char *in2, size_t in2len,
247                 const unsigned char *nonce, size_t noncelen)
248         {
249         DRBG_CTR_CTX *cctx = &dctx->d.ctr;
250         /* ks is already setup for correct key */
251         inc_128(cctx);
252         AES_encrypt(cctx->V, cctx->K, &cctx->ks);
253         /* If keylen longer than 128 bits need extra encrypt */
254         if (cctx->keylen != 16)
255                 {
256                 inc_128(cctx);
257                 AES_encrypt(cctx->V, cctx->K + 16, &cctx->ks);
258                 }
259         inc_128(cctx);
260         AES_encrypt(cctx->V, cctx->V, &cctx->ks);
261         /* If 192 bit key part of V is on end of K */
262         if (cctx->keylen == 24)
263                 {
264                 memcpy(cctx->V + 8, cctx->V, 8);
265                 memcpy(cctx->V, cctx->K + 24, 8);
266                 }
267
268         if (dctx->flags & DRBG_FLAG_CTR_USE_DF)
269                 {
270                 /* If no input reuse existing derived value */
271                 if (in1 || nonce || in2)
272                         ctr_df(cctx, in1, in1len, nonce, noncelen, in2, in2len);
273                 /* If this a reuse input in1len != 0 */
274                 if (in1len)
275                         ctr_XOR(cctx, cctx->KX, dctx->seedlen);
276                 }
277         else
278                 {
279                 ctr_XOR(cctx, in1, in1len);
280                 ctr_XOR(cctx, in2, in2len);
281                 }
282
283         AES_set_encrypt_key(cctx->K, dctx->strength, &cctx->ks);
284 #if 0
285 fprintf(stderr, "K+V after update is:\n");
286 BIO_dump_fp(stderr, cctx->K, cctx->keylen);
287 BIO_dump_fp(stderr, cctx->V, 16);
288 #endif
289         }
290
291 static int drbg_ctr_instantiate(DRBG_CTX *dctx,
292                         const unsigned char *ent, size_t entlen,
293                         const unsigned char *nonce, size_t noncelen,
294                         const unsigned char *pers, size_t perslen)
295         {
296         DRBG_CTR_CTX *cctx = &dctx->d.ctr;
297         memset(cctx->K, 0, sizeof(cctx->K));
298         memset(cctx->V, 0, sizeof(cctx->V));
299         AES_set_encrypt_key(cctx->K, dctx->strength, &cctx->ks);
300         ctr_Update(dctx, ent, entlen, pers, perslen, nonce, noncelen);
301         return 1;
302         }
303
304 static int drbg_ctr_reseed(DRBG_CTX *dctx, 
305                         const unsigned char *ent, size_t entlen,
306                         const unsigned char *adin, size_t adinlen)
307         {
308         ctr_Update(dctx, ent, entlen, adin, adinlen, NULL, 0);
309         return 1;
310         }
311
312 static int drbg_ctr_generate(DRBG_CTX *dctx,
313                         unsigned char *out, size_t outlen,
314                         const unsigned char *adin, size_t adinlen)
315         {
316         DRBG_CTR_CTX *cctx = &dctx->d.ctr;
317         if (adin && adinlen)
318                 {
319                 ctr_Update(dctx, adin, adinlen, NULL, 0, NULL, 0);
320                 /* This means we reuse derived value */
321                 if (dctx->flags & DRBG_FLAG_CTR_USE_DF)
322                         {
323                         adin = NULL;
324                         adinlen = 1;
325                         }
326                 }
327         else
328                 adinlen = 0;
329
330         for (;;)
331                 {
332                 inc_128(cctx);
333                 if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid)
334                         {
335                         AES_encrypt(cctx->V, dctx->lb, &cctx->ks);
336                         dctx->lb_valid = 1;
337                         continue;
338                         }
339                 if (outlen < 16)
340                         {
341                         /* Use K as temp space as it will be updated */
342                         AES_encrypt(cctx->V, cctx->K, &cctx->ks);
343                         if (!fips_drbg_cprng_test(dctx, cctx->K))
344                                 return 0;
345                         memcpy(out, cctx->K, outlen);
346                         break;
347                         }
348                 AES_encrypt(cctx->V, out, &cctx->ks);
349                 if (!fips_drbg_cprng_test(dctx, out))
350                         return 0;
351                 out += 16;
352                 outlen -= 16;
353                 if (outlen == 0)
354                         break;
355                 }
356
357         ctr_Update(dctx, adin, adinlen, NULL, 0, NULL, 0);
358
359         return 1;
360
361         }
362
363 static int drbg_ctr_uninstantiate(DRBG_CTX *dctx)
364         {
365         memset(&dctx->d.ctr, 0, sizeof(DRBG_CTR_CTX));
366         return 1;
367         }
368
369 int fips_drbg_ctr_init(DRBG_CTX *dctx)
370         {
371         DRBG_CTR_CTX *cctx = &dctx->d.ctr;
372
373         size_t keylen;
374
375         switch (dctx->type)
376                 {
377                 case NID_aes_128_ctr:
378                 keylen = 16;
379                 break;
380
381                 case NID_aes_192_ctr:
382                 keylen = 24;
383                 break;
384
385                 case NID_aes_256_ctr:
386                 keylen = 32;
387                 break;
388
389                 default:
390                 return -2;
391                 }
392
393         dctx->instantiate = drbg_ctr_instantiate;
394         dctx->reseed = drbg_ctr_reseed;
395         dctx->generate = drbg_ctr_generate;
396         dctx->uninstantiate = drbg_ctr_uninstantiate;
397
398         cctx->keylen = keylen;
399         dctx->strength = keylen * 8;
400         dctx->blocklength = 16;
401         dctx->seedlen = keylen + 16;
402
403         if (dctx->flags & DRBG_FLAG_CTR_USE_DF)
404                 {
405                 /* df initialisation */
406                 static unsigned char df_key[32] =
407                         {
408                         0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
409                         0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
410                         0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
411                         0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f 
412                         };
413                 /* Set key schedule for df_key */
414                 AES_set_encrypt_key(df_key, dctx->strength, &cctx->df_ks);
415
416                 dctx->min_entropy = cctx->keylen;
417                 dctx->max_entropy = DRBG_MAX_LENGTH;
418                 dctx->min_nonce = dctx->min_entropy / 2;
419                 dctx->max_nonce = DRBG_MAX_LENGTH;
420                 dctx->max_pers = DRBG_MAX_LENGTH;
421                 dctx->max_adin = DRBG_MAX_LENGTH;
422                 }
423         else
424                 {
425                 dctx->min_entropy = dctx->seedlen;
426                 dctx->max_entropy = dctx->seedlen;
427                 /* Nonce not used */
428                 dctx->min_nonce = 0;
429                 dctx->max_nonce = 0;
430                 dctx->max_pers = dctx->seedlen;
431                 dctx->max_adin = dctx->seedlen;
432                 }
433
434         dctx->max_request = 1<<19;
435         dctx->reseed_interval = 1<<24;
436
437         return 1;
438         }