Use function name FIPS_drbg_health_check() for health check function.
[openssl.git] / fips / fips_utl.h
1 /* ====================================================================
2  * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer. 
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  *
48  */
49
50 #define OPENSSL_FIPSAPI
51
52 #include <openssl/fips_rand.h>
53 #include <openssl/objects.h>
54
55 int hex2bin(const char *in, unsigned char *out);
56 unsigned char *hex2bin_m(const char *in, long *plen);
57 int do_hex2bn(BIGNUM **pr, const char *in);
58 int do_bn_print(FILE *out, const BIGNUM *bn);
59 int do_bn_print_name(FILE *out, const char *name, const BIGNUM *bn);
60 int parse_line(char **pkw, char **pval, char *linebuf, char *olinebuf);
61 int parse_line2(char **pkw, char **pval, char *linebuf, char *olinebuf, int eol);
62 BIGNUM *hex2bn(const char *in);
63 int tidy_line(char *linebuf, char *olinebuf);
64 int bint2bin(const char *in, int len, unsigned char *out);
65 int bin2bint(const unsigned char *in,int len,char *out);
66 void PrintValue(char *tag, unsigned char *val, int len);
67 void OutputValue(char *tag, unsigned char *val, int len, FILE *rfp,int bitmode);
68 void fips_algtest_init(void);
69 void do_entropy_stick(void);
70 int fips_strncasecmp(const char *str1, const char *str2, size_t n);
71 int fips_strcasecmp(const char *str1, const char *str2);
72
73 static int no_err;
74
75 static void put_err_cb(int lib, int func,int reason,const char *file,int line)
76         {
77                 if (no_err)
78                         return;
79                 fprintf(stderr, "ERROR:%08lX:lib=%d,func=%d,reason=%d"
80                                 ":file=%s:line=%d\n",
81                         ERR_PACK(lib, func, reason),
82                         lib, func, reason, file, line);
83         }
84
85 static void add_err_cb(int num, va_list args)
86         {
87         int i;
88         char *str;
89         if (no_err)
90                 return;
91         fputs("\t", stderr);
92         for (i = 0; i < num; i++)
93                 {
94                 str = va_arg(args, char *);
95                 if (str)
96                         fputs(str, stderr);
97                 }
98         fputs("\n", stderr);
99         }
100
101 /* Dummy Entropy to keep DRBG happy. WARNING: THIS IS TOTALLY BOGUS
102  * HAS ZERO SECURITY AND MUST NOT BE USED IN REAL APPLICATIONS.
103  */
104
105 static unsigned char dummy_entropy[1024];
106
107 static size_t dummy_cb(DRBG_CTX *ctx, unsigned char **pout,
108                                 int entropy, size_t min_len, size_t max_len)
109         {
110         *pout = dummy_entropy;
111         return min_len;
112         }
113
114 static int entropy_stick = 0;
115
116 static void fips_algtest_init_nofips(void)
117         {
118         DRBG_CTX *ctx;
119         size_t i;
120         FIPS_set_error_callbacks(put_err_cb, add_err_cb);
121         for (i = 0; i < sizeof(dummy_entropy); i++)
122                 dummy_entropy[i] = i & 0xff;
123         if (entropy_stick)
124                 memcpy(dummy_entropy + 32, dummy_entropy + 16, 16);
125         ctx = FIPS_get_default_drbg();
126         FIPS_drbg_init(ctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF);
127         FIPS_drbg_set_callbacks(ctx, dummy_cb, 0, 16, dummy_cb, 0);
128         FIPS_drbg_instantiate(ctx, dummy_entropy, 10);
129         FIPS_rand_set_method(FIPS_drbg_method());
130         }
131
132 void do_entropy_stick(void)
133         {
134         entropy_stick = 1;
135         }
136
137 void fips_algtest_init(void)
138         {
139         fips_algtest_init_nofips();
140         if (!FIPS_module_mode_set(1))
141                 {
142                 fprintf(stderr, "Error entering FIPS mode\n");
143                 exit(1);
144                 }
145         }
146
147 int hex2bin(const char *in, unsigned char *out)
148     {
149     int n1, n2, isodd = 0;
150     unsigned char ch;
151
152     n1 = strlen(in);
153     if (in[n1 - 1] == '\n')
154         n1--;
155
156     if (n1 & 1)
157         isodd = 1;
158
159     for (n1=0,n2=0 ; in[n1] && in[n1] != '\n' ; )
160         { /* first byte */
161         if ((in[n1] >= '0') && (in[n1] <= '9'))
162             ch = in[n1++] - '0';
163         else if ((in[n1] >= 'A') && (in[n1] <= 'F'))
164             ch = in[n1++] - 'A' + 10;
165         else if ((in[n1] >= 'a') && (in[n1] <= 'f'))
166             ch = in[n1++] - 'a' + 10;
167         else
168             return -1;
169         if(!in[n1])
170             {
171             out[n2++]=ch;
172             break;
173             }
174         /* If input is odd length first digit is least significant: assumes
175          * all digits valid hex and null terminated which is true for the
176          * strings we pass.
177          */
178         if (n1 == 1 && isodd)
179                 {
180                 out[n2++] = ch;
181                 continue;
182                 }
183         out[n2] = ch << 4;
184         /* second byte */
185         if ((in[n1] >= '0') && (in[n1] <= '9'))
186             ch = in[n1++] - '0';
187         else if ((in[n1] >= 'A') && (in[n1] <= 'F'))
188             ch = in[n1++] - 'A' + 10;
189         else if ((in[n1] >= 'a') && (in[n1] <= 'f'))
190             ch = in[n1++] - 'a' + 10;
191         else
192             return -1;
193         out[n2++] |= ch;
194         }
195     return n2;
196     }
197
198 unsigned char *hex2bin_m(const char *in, long *plen)
199         {
200         unsigned char *p;
201         if (strlen(in) == 0)
202                 {
203                 *plen = 0;
204                 return OPENSSL_malloc(1);
205                 }
206         p = OPENSSL_malloc((strlen(in) + 1)/2);
207         *plen = hex2bin(in, p);
208         return p;
209         }
210
211 int do_hex2bn(BIGNUM **pr, const char *in)
212         {
213         unsigned char *p;
214         long plen;
215         int r = 0;
216         p = hex2bin_m(in, &plen);
217         if (!p)
218                 return 0;
219         if (!*pr)
220                 *pr = BN_new();
221         if (!*pr)
222                 return 0;
223         if (BN_bin2bn(p, plen, *pr))
224                 r = 1;
225         OPENSSL_free(p);
226         return r;
227         }
228
229 int do_bn_print(FILE *out, const BIGNUM *bn)
230         {
231         int len, i;
232         unsigned char *tmp;
233         len = BN_num_bytes(bn);
234         if (len == 0)
235                 {
236                 fputs("00", out);
237                 return 1;
238                 }
239
240         tmp = OPENSSL_malloc(len);
241         if (!tmp)
242                 {
243                 fprintf(stderr, "Memory allocation error\n");
244                 return 0;
245                 }
246         BN_bn2bin(bn, tmp);
247         for (i = 0; i < len; i++)
248                 fprintf(out, "%02x", tmp[i]);
249         OPENSSL_free(tmp);
250         return 1;
251         }
252
253 int do_bn_print_name(FILE *out, const char *name, const BIGNUM *bn)
254         {
255         int r;
256         fprintf(out, "%s = ", name);
257         r = do_bn_print(out, bn);
258         if (!r)
259                 return 0;
260         fputs("\n", out);
261         return 1;
262         }
263
264 int parse_line(char **pkw, char **pval, char *linebuf, char *olinebuf)
265         {
266         return parse_line2(pkw, pval, linebuf, olinebuf, 1);
267         }
268
269 int parse_line2(char **pkw, char **pval, char *linebuf, char *olinebuf, int eol)
270         {
271         char *keyword, *value, *p, *q;
272         strcpy(linebuf, olinebuf);
273         keyword = linebuf;
274         /* Skip leading space */
275         while (isspace((unsigned char)*keyword))
276                 keyword++;
277
278         /* Look for = sign */
279         p = strchr(linebuf, '=');
280
281         /* If no '=' exit */
282         if (!p)
283                 return 0;
284
285         q = p - 1;
286
287         /* Remove trailing space */
288         while (isspace((unsigned char)*q))
289                 *q-- = 0;
290
291         *p = 0;
292         value = p + 1;
293
294         /* Remove leading space from value */
295         while (isspace((unsigned char)*value))
296                 value++;
297
298         /* Remove trailing space from value */
299         p = value + strlen(value) - 1;
300
301         if (eol && *p != '\n')
302                 fprintf(stderr, "Warning: missing EOL\n");
303
304         while (*p == '\n' || isspace((unsigned char)*p))
305                 *p-- = 0;
306
307         *pkw = keyword;
308         *pval = value;
309         return 1;
310         }
311
312 BIGNUM *hex2bn(const char *in)
313     {
314     BIGNUM *p=NULL;
315
316     if (!do_hex2bn(&p, in))
317         return NULL;
318
319     return p;
320     }
321
322 /* To avoid extensive changes to test program at this stage just convert
323  * the input line into an acceptable form. Keyword lines converted to form
324  * "keyword = value\n" no matter what white space present, all other lines
325  * just have leading and trailing space removed.
326  */
327
328 int tidy_line(char *linebuf, char *olinebuf)
329         {
330         char *keyword, *value, *p, *q;
331         strcpy(linebuf, olinebuf);
332         keyword = linebuf;
333         /* Skip leading space */
334         while (isspace((unsigned char)*keyword))
335                 keyword++;
336         /* Look for = sign */
337         p = strchr(linebuf, '=');
338
339         /* If no '=' just chop leading, trailing ws */
340         if (!p)
341                 {
342                 p = keyword + strlen(keyword) - 1;
343                 while (*p == '\n' || isspace((unsigned char)*p))
344                         *p-- = 0;
345                 strcpy(olinebuf, keyword);
346                 strcat(olinebuf, "\n");
347                 return 1;
348                 }
349
350         q = p - 1;
351
352         /* Remove trailing space */
353         while (isspace((unsigned char)*q))
354                 *q-- = 0;
355
356         *p = 0;
357         value = p + 1;
358
359         /* Remove leading space from value */
360         while (isspace((unsigned char)*value))
361                 value++;
362
363         /* Remove trailing space from value */
364         p = value + strlen(value) - 1;
365
366         while (*p == '\n' || isspace((unsigned char)*p))
367                 *p-- = 0;
368
369         strcpy(olinebuf, keyword);
370         strcat(olinebuf, " = ");
371         strcat(olinebuf, value);
372         strcat(olinebuf, "\n");
373
374         return 1;
375         }
376
377 /* NB: this return the number of _bits_ read */
378 int bint2bin(const char *in, int len, unsigned char *out)
379     {
380     int n;
381
382     memset(out,0,len);
383     for(n=0 ; n < len ; ++n)
384         if(in[n] == '1')
385             out[n/8]|=(0x80 >> (n%8));
386     return len;
387     }
388
389 int bin2bint(const unsigned char *in,int len,char *out)
390     {
391     int n;
392
393     for(n=0 ; n < len ; ++n)
394         out[n]=(in[n/8]&(0x80 >> (n%8))) ? '1' : '0';
395     return n;
396     }
397
398 /*-----------------------------------------------*/
399
400 void PrintValue(char *tag, unsigned char *val, int len)
401 {
402 #ifdef VERBOSE
403         OutputValue(tag, val, len, stdout, 0);
404 #endif
405 }
406
407 void OutputValue(char *tag, unsigned char *val, int len, FILE *rfp,int bitmode)
408     {
409     char obuf[2048];
410     int olen;
411
412     if(bitmode)
413         {
414         olen=bin2bint(val,len,obuf);
415         fprintf(rfp, "%s = %.*s\n", tag, olen, obuf);
416         }
417     else
418         {
419         int i;
420         fprintf(rfp, "%s = ", tag);
421         for (i = 0; i < len; i++)
422                 fprintf(rfp, "%02x", val[i]);
423         fputs("\n", rfp);
424         }
425
426 #if VERBOSE
427     printf("%s = %.*s\n", tag, olen, obuf);
428 #endif
429     }
430
431 /* Not all platforms support strcasecmp and strncasecmp: implement versions
432  * in here to avoid need to include them in the validated module. Taken
433  * from crypto/o_str.c written by Richard Levitte (richard@levitte.org)
434  */
435
436 int fips_strncasecmp(const char *str1, const char *str2, size_t n)
437         {
438         while (*str1 && *str2 && n)
439                 {
440                 int res = toupper(*str1) - toupper(*str2);
441                 if (res) return res < 0 ? -1 : 1;
442                 str1++;
443                 str2++;
444                 n--;
445                 }
446         if (n == 0)
447                 return 0;
448         if (*str1)
449                 return 1;
450         if (*str2)
451                 return -1;
452         return 0;
453         }
454
455 int fips_strcasecmp(const char *str1, const char *str2)
456         {
457         return fips_strncasecmp(str1, str2, (size_t)-1);
458         }
459