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