fips/fips_[canister|premain].c: make it work with VC6 and add sentinels
[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 #ifdef OPENSSL_SYS_WIN32
56 #define RESP_EOL        "\n"
57 #else
58 #define RESP_EOL        "\r\n"
59 #endif
60
61 #ifndef FIPS_AUTH_OFFICER_PASS
62 #define FIPS_AUTH_OFFICER_PASS  "Default FIPS Crypto Officer Password"
63 #endif
64
65 #ifndef FIPS_AUTH_USER_PASS
66 #define FIPS_AUTH_USER_PASS     "Default FIPS Crypto User Password"
67 #endif
68
69
70 int hex2bin(const char *in, unsigned char *out);
71 unsigned char *hex2bin_m(const char *in, long *plen);
72 int do_hex2bn(BIGNUM **pr, const char *in);
73 int do_bn_print(FILE *out, const BIGNUM *bn);
74 int do_bn_print_name(FILE *out, const char *name, const BIGNUM *bn);
75 int parse_line(char **pkw, char **pval, char *linebuf, char *olinebuf);
76 int parse_line2(char **pkw, char **pval, char *linebuf, char *olinebuf, int eol);
77 BIGNUM *hex2bn(const char *in);
78 int tidy_line(char *linebuf, char *olinebuf);
79 int copy_line(const char *in, FILE *ofp);
80 int bint2bin(const char *in, int len, unsigned char *out);
81 int bin2bint(const unsigned char *in,int len,char *out);
82 void PrintValue(char *tag, unsigned char *val, int len);
83 void OutputValue(char *tag, unsigned char *val, int len, FILE *rfp,int bitmode);
84 void fips_algtest_init(void);
85 void do_entropy_stick(void);
86 int fips_strncasecmp(const char *str1, const char *str2, size_t n);
87 int fips_strcasecmp(const char *str1, const char *str2);
88
89 static int no_err;
90
91 static void put_err_cb(int lib, int func,int reason,const char *file,int line)
92         {
93         if (no_err)
94                 return;
95         fprintf(stderr, "ERROR:%08lX:lib=%d,func=%d,reason=%d"
96                                 ":file=%s:line=%d\n",
97                         ERR_PACK(lib, func, reason),
98                         lib, func, reason, file, line);
99         }
100
101 static void add_err_cb(int num, va_list args)
102         {
103         int i;
104         char *str;
105         if (no_err)
106                 return;
107         fputs("\t", stderr);
108         for (i = 0; i < num; i++)
109                 {
110                 str = va_arg(args, char *);
111                 if (str)
112                         fputs(str, stderr);
113                 }
114         fputs("\n", stderr);
115         }
116
117 /* Dummy Entropy to keep DRBG happy. WARNING: THIS IS TOTALLY BOGUS
118  * HAS ZERO SECURITY AND MUST NOT BE USED IN REAL APPLICATIONS.
119  */
120
121 static unsigned char dummy_entropy[1024];
122
123 static size_t dummy_cb(DRBG_CTX *ctx, unsigned char **pout,
124                                 int entropy, size_t min_len, size_t max_len)
125         {
126         *pout = dummy_entropy;
127         return min_len;
128         }
129
130 static int entropy_stick = 0;
131
132 static void fips_algtest_init_nofips(void)
133         {
134         DRBG_CTX *ctx;
135         size_t i;
136         FIPS_set_error_callbacks(put_err_cb, add_err_cb);
137         for (i = 0; i < sizeof(dummy_entropy); i++)
138                 dummy_entropy[i] = i & 0xff;
139         if (entropy_stick)
140                 memcpy(dummy_entropy + 32, dummy_entropy + 16, 16);
141         ctx = FIPS_get_default_drbg();
142         FIPS_drbg_init(ctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF);
143         FIPS_drbg_set_callbacks(ctx, dummy_cb, 0, 16, dummy_cb, 0);
144         FIPS_drbg_instantiate(ctx, dummy_entropy, 10);
145         FIPS_rand_set_method(FIPS_drbg_method());
146         }
147
148 void do_entropy_stick(void)
149         {
150         entropy_stick = 1;
151         }
152
153 void fips_algtest_init(void)
154         {
155         fips_algtest_init_nofips();
156         if (!FIPS_module_mode_set(1, FIPS_AUTH_USER_PASS))
157                 {
158                 fprintf(stderr, "Error entering FIPS mode\n");
159                 exit(1);
160                 }
161         }
162
163 int hex2bin(const char *in, unsigned char *out)
164     {
165     int n1, n2, isodd = 0;
166     unsigned char ch;
167
168     n1 = strlen(in);
169     if (in[n1 - 1] == '\n')
170         n1--;
171
172     if (n1 & 1)
173         isodd = 1;
174
175     for (n1=0,n2=0 ; in[n1] && in[n1] != '\n' ; )
176         { /* first byte */
177         if ((in[n1] >= '0') && (in[n1] <= '9'))
178             ch = in[n1++] - '0';
179         else if ((in[n1] >= 'A') && (in[n1] <= 'F'))
180             ch = in[n1++] - 'A' + 10;
181         else if ((in[n1] >= 'a') && (in[n1] <= 'f'))
182             ch = in[n1++] - 'a' + 10;
183         else
184             return -1;
185         if(!in[n1])
186             {
187             out[n2++]=ch;
188             break;
189             }
190         /* If input is odd length first digit is least significant: assumes
191          * all digits valid hex and null terminated which is true for the
192          * strings we pass.
193          */
194         if (n1 == 1 && isodd)
195                 {
196                 out[n2++] = ch;
197                 continue;
198                 }
199         out[n2] = ch << 4;
200         /* second byte */
201         if ((in[n1] >= '0') && (in[n1] <= '9'))
202             ch = in[n1++] - '0';
203         else if ((in[n1] >= 'A') && (in[n1] <= 'F'))
204             ch = in[n1++] - 'A' + 10;
205         else if ((in[n1] >= 'a') && (in[n1] <= 'f'))
206             ch = in[n1++] - 'a' + 10;
207         else
208             return -1;
209         out[n2++] |= ch;
210         }
211     return n2;
212     }
213
214 unsigned char *hex2bin_m(const char *in, long *plen)
215         {
216         unsigned char *p;
217         if (strlen(in) == 0)
218                 {
219                 *plen = 0;
220                 return OPENSSL_malloc(1);
221                 }
222         p = OPENSSL_malloc((strlen(in) + 1)/2);
223         *plen = hex2bin(in, p);
224         return p;
225         }
226
227 int do_hex2bn(BIGNUM **pr, const char *in)
228         {
229         unsigned char *p;
230         long plen;
231         int r = 0;
232         p = hex2bin_m(in, &plen);
233         if (!p)
234                 return 0;
235         if (!*pr)
236                 *pr = BN_new();
237         if (!*pr)
238                 return 0;
239         if (BN_bin2bn(p, plen, *pr))
240                 r = 1;
241         OPENSSL_free(p);
242         return r;
243         }
244
245 int do_bn_print(FILE *out, const BIGNUM *bn)
246         {
247         int len, i;
248         unsigned char *tmp;
249         len = BN_num_bytes(bn);
250         if (len == 0)
251                 {
252                 fputs("00", out);
253                 return 1;
254                 }
255
256         tmp = OPENSSL_malloc(len);
257         if (!tmp)
258                 {
259                 fprintf(stderr, "Memory allocation error\n");
260                 return 0;
261                 }
262         BN_bn2bin(bn, tmp);
263         for (i = 0; i < len; i++)
264                 fprintf(out, "%02x", tmp[i]);
265         OPENSSL_free(tmp);
266         return 1;
267         }
268
269 int do_bn_print_name(FILE *out, const char *name, const BIGNUM *bn)
270         {
271         int r;
272         fprintf(out, "%s = ", name);
273         r = do_bn_print(out, bn);
274         if (!r)
275                 return 0;
276         fputs(RESP_EOL, out);
277         return 1;
278         }
279
280 int parse_line(char **pkw, char **pval, char *linebuf, char *olinebuf)
281         {
282         return parse_line2(pkw, pval, linebuf, olinebuf, 1);
283         }
284
285 int parse_line2(char **pkw, char **pval, char *linebuf, char *olinebuf, int eol)
286         {
287         char *keyword, *value, *p, *q;
288         strcpy(linebuf, olinebuf);
289         keyword = linebuf;
290         /* Skip leading space */
291         while (isspace((unsigned char)*keyword))
292                 keyword++;
293
294         /* Look for = sign */
295         p = strchr(linebuf, '=');
296
297         /* If no '=' exit */
298         if (!p)
299                 return 0;
300
301         q = p - 1;
302
303         /* Remove trailing space */
304         while (isspace((unsigned char)*q))
305                 *q-- = 0;
306
307         *p = 0;
308         value = p + 1;
309
310         /* Remove leading space from value */
311         while (isspace((unsigned char)*value))
312                 value++;
313
314         /* Remove trailing space from value */
315         p = value + strlen(value) - 1;
316
317         if (eol && *p != '\n')
318                 fprintf(stderr, "Warning: missing EOL\n");
319
320         while (*p == '\n' || isspace((unsigned char)*p))
321                 *p-- = 0;
322
323         *pkw = keyword;
324         *pval = value;
325         return 1;
326         }
327
328 BIGNUM *hex2bn(const char *in)
329     {
330     BIGNUM *p=NULL;
331
332     if (!do_hex2bn(&p, in))
333         return NULL;
334
335     return p;
336     }
337
338 /* To avoid extensive changes to test program at this stage just convert
339  * the input line into an acceptable form. Keyword lines converted to form
340  * "keyword = value\n" no matter what white space present, all other lines
341  * just have leading and trailing space removed.
342  */
343
344 int tidy_line(char *linebuf, char *olinebuf)
345         {
346         char *keyword, *value, *p, *q;
347         strcpy(linebuf, olinebuf);
348         keyword = linebuf;
349         /* Skip leading space */
350         while (isspace((unsigned char)*keyword))
351                 keyword++;
352         /* Look for = sign */
353         p = strchr(linebuf, '=');
354
355         /* If no '=' just chop leading, trailing ws */
356         if (!p)
357                 {
358                 p = keyword + strlen(keyword) - 1;
359                 while (*p == '\n' || isspace((unsigned char)*p))
360                         *p-- = 0;
361                 strcpy(olinebuf, keyword);
362                 strcat(olinebuf, "\n");
363                 return 1;
364                 }
365
366         q = p - 1;
367
368         /* Remove trailing space */
369         while (isspace((unsigned char)*q))
370                 *q-- = 0;
371
372         *p = 0;
373         value = p + 1;
374
375         /* Remove leading space from value */
376         while (isspace((unsigned char)*value))
377                 value++;
378
379         /* Remove trailing space from value */
380         p = value + strlen(value) - 1;
381
382         while (*p == '\n' || isspace((unsigned char)*p))
383                 *p-- = 0;
384
385         strcpy(olinebuf, keyword);
386         strcat(olinebuf, " = ");
387         strcat(olinebuf, value);
388         strcat(olinebuf, "\n");
389
390         return 1;
391         }
392 /* Copy supplied line to ofp replacing \n with \r\n */
393 int copy_line(const char *in, FILE *ofp)
394         {
395         const char *p;
396         p = strchr(in, '\n');
397         if (p)
398                 {
399                 fwrite(in, 1, (size_t)(p - in), ofp);
400                 fputs(RESP_EOL, ofp);
401                 }
402         else
403                 fputs(in, ofp);
404         return 1;
405         }
406
407 /* NB: this return the number of _bits_ read */
408 int bint2bin(const char *in, int len, unsigned char *out)
409     {
410     int n;
411
412     memset(out,0,len);
413     for(n=0 ; n < len ; ++n)
414         if(in[n] == '1')
415             out[n/8]|=(0x80 >> (n%8));
416     return len;
417     }
418
419 int bin2bint(const unsigned char *in,int len,char *out)
420     {
421     int n;
422
423     for(n=0 ; n < len ; ++n)
424         out[n]=(in[n/8]&(0x80 >> (n%8))) ? '1' : '0';
425     return n;
426     }
427
428 /*-----------------------------------------------*/
429
430 void PrintValue(char *tag, unsigned char *val, int len)
431 {
432 #ifdef VERBOSE
433         OutputValue(tag, val, len, stdout, 0);
434 #endif
435 }
436
437 void OutputValue(char *tag, unsigned char *val, int len, FILE *rfp,int bitmode)
438     {
439     char obuf[2048];
440     int olen;
441
442     if(bitmode)
443         {
444         olen=bin2bint(val,len,obuf);
445         fprintf(rfp, "%s = %.*s" RESP_EOL, tag, olen, obuf);
446         }
447     else
448         {
449         int i;
450         fprintf(rfp, "%s = ", tag);
451         for (i = 0; i < len; i++)
452                 fprintf(rfp, "%02x", val[i]);
453         fputs(RESP_EOL, rfp);
454         }
455
456 #if VERBOSE
457     printf("%s = %.*s\n", tag, olen, obuf);
458 #endif
459     }
460
461 /* Not all platforms support strcasecmp and strncasecmp: implement versions
462  * in here to avoid need to include them in the validated module. Taken
463  * from crypto/o_str.c written by Richard Levitte (richard@levitte.org)
464  */
465
466 int fips_strncasecmp(const char *str1, const char *str2, size_t n)
467         {
468         while (*str1 && *str2 && n)
469                 {
470                 int res = toupper(*str1) - toupper(*str2);
471                 if (res) return res < 0 ? -1 : 1;
472                 str1++;
473                 str2++;
474                 n--;
475                 }
476         if (n == 0)
477                 return 0;
478         if (*str1)
479                 return 1;
480         if (*str2)
481                 return -1;
482         return 0;
483         }
484
485 int fips_strcasecmp(const char *str1, const char *str2)
486         {
487         return fips_strncasecmp(str1, str2, (size_t)-1);
488         }
489