fips_rsavtest.c revision 296465
1/* fips_rsavtest.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 2005. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2005 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdio.h> 61#include <ctype.h> 62#include <string.h> 63#include <openssl/bio.h> 64#include <openssl/evp.h> 65#include <openssl/hmac.h> 66#include <openssl/err.h> 67#include <openssl/x509v3.h> 68#include <openssl/bn.h> 69 70#ifndef OPENSSL_FIPS 71 72int main(int argc, char *argv[]) 73{ 74 printf("No FIPS RSA support\n"); 75 return (0); 76} 77 78#else 79 80# include <openssl/rsa.h> 81 82# include "fips_utl.h" 83 84int rsa_test(FILE *out, FILE *in, int saltlen); 85static int rsa_printver(FILE *out, 86 BIGNUM *n, BIGNUM *e, 87 const EVP_MD *dgst, 88 unsigned char *Msg, long Msglen, 89 unsigned char *S, long Slen, int Saltlen); 90 91int main(int argc, char **argv) 92{ 93 FILE *in = NULL, *out = NULL; 94 95 int ret = 1; 96 int Saltlen = -1; 97 98 if (!FIPS_mode_set(1)) { 99 do_print_errors(); 100 goto end; 101 } 102 103 if ((argc > 2) && !strcmp("-saltlen", argv[1])) { 104 Saltlen = atoi(argv[2]); 105 if (Saltlen < 0) { 106 fprintf(stderr, "FATAL: Invalid salt length\n"); 107 goto end; 108 } 109 argc -= 2; 110 argv += 2; 111 } else if ((argc > 1) && !strcmp("-x931", argv[1])) { 112 Saltlen = -2; 113 argc--; 114 argv++; 115 } 116 117 if (argc == 1) 118 in = stdin; 119 else 120 in = fopen(argv[1], "r"); 121 122 if (argc < 2) 123 out = stdout; 124 else 125 out = fopen(argv[2], "w"); 126 127 if (!in) { 128 fprintf(stderr, "FATAL input initialization error\n"); 129 goto end; 130 } 131 132 if (!out) { 133 fprintf(stderr, "FATAL output initialization error\n"); 134 goto end; 135 } 136 137 if (!rsa_test(out, in, Saltlen)) { 138 fprintf(stderr, "FATAL RSAVTEST file processing error\n"); 139 goto end; 140 } else 141 ret = 0; 142 143 end: 144 145 if (ret) 146 do_print_errors(); 147 148 if (in && (in != stdin)) 149 fclose(in); 150 if (out && (out != stdout)) 151 fclose(out); 152 153 return ret; 154 155} 156 157# define RSA_TEST_MAXLINELEN 10240 158 159int rsa_test(FILE *out, FILE *in, int Saltlen) 160{ 161 char *linebuf, *olinebuf, *p, *q; 162 char *keyword, *value; 163 const EVP_MD *dgst = NULL; 164 BIGNUM *n = NULL, *e = NULL; 165 unsigned char *Msg = NULL, *S = NULL; 166 long Msglen, Slen; 167 int ret = 0; 168 int lnum = 0; 169 170 olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 171 linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 172 173 if (!linebuf || !olinebuf) 174 goto error; 175 176 while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) { 177 lnum++; 178 strcpy(linebuf, olinebuf); 179 keyword = linebuf; 180 /* Skip leading space */ 181 while (isspace((unsigned char)*keyword)) 182 keyword++; 183 184 /* Look for = sign */ 185 p = strchr(linebuf, '='); 186 187 /* 188 * If no = or starts with [ (for [foo = bar] line) just copy 189 */ 190 if (!p || *keyword == '[') { 191 if (fputs(olinebuf, out) < 0) 192 goto error; 193 continue; 194 } 195 196 q = p - 1; 197 198 /* Remove trailing space */ 199 while (isspace((unsigned char)*q)) 200 *q-- = 0; 201 202 *p = 0; 203 value = p + 1; 204 205 /* Remove leading space from value */ 206 while (isspace((unsigned char)*value)) 207 value++; 208 209 /* Remove trailing space from value */ 210 p = value + strlen(value) - 1; 211 212 while (*p == '\n' || isspace((unsigned char)*p)) 213 *p-- = 0; 214 215 if (!strcmp(keyword, "n")) { 216 if (!do_hex2bn(&n, value)) 217 goto parse_error; 218 } else if (!strcmp(keyword, "e")) { 219 if (!do_hex2bn(&e, value)) 220 goto parse_error; 221 } else if (!strcmp(keyword, "SHAAlg")) { 222 if (!strcmp(value, "SHA1")) 223 dgst = EVP_sha1(); 224 else if (!strcmp(value, "SHA224")) 225 dgst = EVP_sha224(); 226 else if (!strcmp(value, "SHA256")) 227 dgst = EVP_sha256(); 228 else if (!strcmp(value, "SHA384")) 229 dgst = EVP_sha384(); 230 else if (!strcmp(value, "SHA512")) 231 dgst = EVP_sha512(); 232 else { 233 fprintf(stderr, 234 "FATAL: unsupported algorithm \"%s\"\n", value); 235 goto parse_error; 236 } 237 } else if (!strcmp(keyword, "Msg")) { 238 if (Msg) 239 goto parse_error; 240 if (strlen(value) & 1) 241 *(--value) = '0'; 242 Msg = hex2bin_m(value, &Msglen); 243 if (!Msg) 244 goto parse_error; 245 } else if (!strcmp(keyword, "S")) { 246 if (S) 247 goto parse_error; 248 if (strlen(value) & 1) 249 *(--value) = '0'; 250 S = hex2bin_m(value, &Slen); 251 if (!S) 252 goto parse_error; 253 } else if (!strcmp(keyword, "Result")) 254 continue; 255 else 256 goto parse_error; 257 258 fputs(olinebuf, out); 259 260 if (n && e && Msg && S && dgst) { 261 if (!rsa_printver(out, n, e, dgst, Msg, Msglen, S, Slen, Saltlen)) 262 goto error; 263 OPENSSL_free(Msg); 264 Msg = NULL; 265 OPENSSL_free(S); 266 S = NULL; 267 } 268 269 } 270 271 ret = 1; 272 273 error: 274 275 if (olinebuf) 276 OPENSSL_free(olinebuf); 277 if (linebuf) 278 OPENSSL_free(linebuf); 279 if (n) 280 BN_free(n); 281 if (e) 282 BN_free(e); 283 284 return ret; 285 286 parse_error: 287 288 fprintf(stderr, "FATAL parse error processing line %d\n", lnum); 289 290 goto error; 291 292} 293 294static int rsa_printver(FILE *out, 295 BIGNUM *n, BIGNUM *e, 296 const EVP_MD *dgst, 297 unsigned char *Msg, long Msglen, 298 unsigned char *S, long Slen, int Saltlen) 299{ 300 int ret = 0, r; 301 /* Setup RSA and EVP_PKEY structures */ 302 RSA *rsa_pubkey = NULL; 303 EVP_PKEY pk; 304 EVP_MD_CTX ctx; 305 unsigned char *buf = NULL; 306 rsa_pubkey = FIPS_rsa_new(); 307 if (!rsa_pubkey) 308 goto error; 309 rsa_pubkey->n = BN_dup(n); 310 rsa_pubkey->e = BN_dup(e); 311 if (!rsa_pubkey->n || !rsa_pubkey->e) 312 goto error; 313 pk.type = EVP_PKEY_RSA; 314 pk.pkey.rsa = rsa_pubkey; 315 316 EVP_MD_CTX_init(&ctx); 317 318 if (Saltlen >= 0) { 319 M_EVP_MD_CTX_set_flags(&ctx, 320 EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16)); 321 } else if (Saltlen == -2) 322 M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931); 323 if (!EVP_VerifyInit_ex(&ctx, dgst, NULL)) 324 goto error; 325 if (!EVP_VerifyUpdate(&ctx, Msg, Msglen)) 326 goto error; 327 328 r = EVP_VerifyFinal(&ctx, S, Slen, &pk); 329 330 EVP_MD_CTX_cleanup(&ctx); 331 332 if (r < 0) 333 goto error; 334 ERR_clear_error(); 335 336 if (r == 0) 337 fputs("Result = F\n", out); 338 else 339 fputs("Result = P\n", out); 340 341 ret = 1; 342 343 error: 344 if (rsa_pubkey) 345 FIPS_rsa_free(rsa_pubkey); 346 if (buf) 347 OPENSSL_free(buf); 348 349 return ret; 350} 351#endif 352