1/* fips_rsastest.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/bn.h> 68#include <openssl/x509v3.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# include "fips_utl.h" 82 83static int rsa_stest(FILE *out, FILE *in, int Saltlen); 84static int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst, 85 unsigned char *Msg, long Msglen, int Saltlen); 86 87int main(int argc, char **argv) 88{ 89 FILE *in = NULL, *out = NULL; 90 91 int ret = 1, Saltlen = -1; 92 93 if (!FIPS_mode_set(1)) { 94 do_print_errors(); 95 goto end; 96 } 97 98 if ((argc > 2) && !strcmp("-saltlen", argv[1])) { 99 Saltlen = atoi(argv[2]); 100 if (Saltlen < 0) { 101 fprintf(stderr, "FATAL: Invalid salt length\n"); 102 goto end; 103 } 104 argc -= 2; 105 argv += 2; 106 } else if ((argc > 1) && !strcmp("-x931", argv[1])) { 107 Saltlen = -2; 108 argc--; 109 argv++; 110 } 111 112 if (argc == 1) 113 in = stdin; 114 else 115 in = fopen(argv[1], "r"); 116 117 if (argc < 2) 118 out = stdout; 119 else 120 out = fopen(argv[2], "w"); 121 122 if (!in) { 123 fprintf(stderr, "FATAL input initialization error\n"); 124 goto end; 125 } 126 127 if (!out) { 128 fprintf(stderr, "FATAL output initialization error\n"); 129 goto end; 130 } 131 132 if (!rsa_stest(out, in, Saltlen)) { 133 fprintf(stderr, "FATAL RSASTEST file processing error\n"); 134 goto end; 135 } else 136 ret = 0; 137 138 end: 139 140 if (ret) 141 do_print_errors(); 142 143 if (in && (in != stdin)) 144 fclose(in); 145 if (out && (out != stdout)) 146 fclose(out); 147 148 return ret; 149 150} 151 152# define RSA_TEST_MAXLINELEN 10240 153 154int rsa_stest(FILE *out, FILE *in, int Saltlen) 155{ 156 char *linebuf, *olinebuf, *p, *q; 157 char *keyword, *value; 158 RSA *rsa = NULL; 159 const EVP_MD *dgst = NULL; 160 unsigned char *Msg = NULL; 161 long Msglen = -1; 162 int keylen = -1, current_keylen = -1; 163 int ret = 0; 164 int lnum = 0; 165 166 olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 167 linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 168 169 if (!linebuf || !olinebuf) 170 goto error; 171 172 while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) { 173 lnum++; 174 strcpy(linebuf, olinebuf); 175 keyword = linebuf; 176 /* Skip leading space */ 177 while (isspace((unsigned char)*keyword)) 178 keyword++; 179 180 /* Look for = sign */ 181 p = strchr(linebuf, '='); 182 183 /* If no = just copy */ 184 if (!p) { 185 if (fputs(olinebuf, out) < 0) 186 goto error; 187 continue; 188 } 189 190 q = p - 1; 191 192 /* Remove trailing space */ 193 while (isspace((unsigned char)*q)) 194 *q-- = 0; 195 196 *p = 0; 197 value = p + 1; 198 199 /* Remove leading space from value */ 200 while (isspace((unsigned char)*value)) 201 value++; 202 203 /* Remove trailing space from value */ 204 p = value + strlen(value) - 1; 205 206 while (*p == '\n' || isspace((unsigned char)*p)) 207 *p-- = 0; 208 209 /* Look for [mod = XXX] for key length */ 210 211 if (!strcmp(keyword, "[mod")) { 212 p = value + strlen(value) - 1; 213 if (*p != ']') 214 goto parse_error; 215 *p = 0; 216 keylen = atoi(value); 217 if (keylen < 0) 218 goto parse_error; 219 } else if (!strcmp(keyword, "SHAAlg")) { 220 if (!strcmp(value, "SHA1")) 221 dgst = EVP_sha1(); 222 else if (!strcmp(value, "SHA224")) 223 dgst = EVP_sha224(); 224 else if (!strcmp(value, "SHA256")) 225 dgst = EVP_sha256(); 226 else if (!strcmp(value, "SHA384")) 227 dgst = EVP_sha384(); 228 else if (!strcmp(value, "SHA512")) 229 dgst = EVP_sha512(); 230 else { 231 fprintf(stderr, 232 "FATAL: unsupported algorithm \"%s\"\n", value); 233 goto parse_error; 234 } 235 } else if (!strcmp(keyword, "Msg")) { 236 if (Msg) 237 goto parse_error; 238 if (strlen(value) & 1) 239 *(--value) = '0'; 240 Msg = hex2bin_m(value, &Msglen); 241 if (!Msg) 242 goto parse_error; 243 } 244 245 fputs(olinebuf, out); 246 247 /* 248 * If key length has changed, generate and output public key 249 * components of new RSA private key. 250 */ 251 252 if (keylen != current_keylen) { 253 BIGNUM *bn_e; 254 if (rsa) 255 FIPS_rsa_free(rsa); 256 rsa = FIPS_rsa_new(); 257 if (!rsa) 258 goto error; 259 bn_e = BN_new(); 260 if (!bn_e || !BN_set_word(bn_e, 0x1001)) 261 goto error; 262 if (!RSA_X931_generate_key_ex(rsa, keylen, bn_e, NULL)) 263 goto error; 264 BN_free(bn_e); 265 fputs("n = ", out); 266 do_bn_print(out, rsa->n); 267 fputs("\ne = ", out); 268 do_bn_print(out, rsa->e); 269 fputs("\n", out); 270 current_keylen = keylen; 271 } 272 273 if (Msg && dgst) { 274 if (!rsa_printsig(out, rsa, dgst, Msg, Msglen, Saltlen)) 275 goto error; 276 OPENSSL_free(Msg); 277 Msg = NULL; 278 } 279 280 } 281 282 ret = 1; 283 284 error: 285 286 if (olinebuf) 287 OPENSSL_free(olinebuf); 288 if (linebuf) 289 OPENSSL_free(linebuf); 290 if (rsa) 291 FIPS_rsa_free(rsa); 292 293 return ret; 294 295 parse_error: 296 297 fprintf(stderr, "FATAL parse error processing line %d\n", lnum); 298 299 goto error; 300 301} 302 303static int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst, 304 unsigned char *Msg, long Msglen, int Saltlen) 305{ 306 int ret = 0; 307 unsigned char *sigbuf = NULL; 308 int i, siglen; 309 /* EVP_PKEY structure */ 310 EVP_PKEY pk; 311 EVP_MD_CTX ctx; 312 pk.type = EVP_PKEY_RSA; 313 pk.pkey.rsa = rsa; 314 315 siglen = RSA_size(rsa); 316 sigbuf = OPENSSL_malloc(siglen); 317 if (!sigbuf) 318 goto error; 319 320 EVP_MD_CTX_init(&ctx); 321 322 if (Saltlen >= 0) { 323 M_EVP_MD_CTX_set_flags(&ctx, 324 EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16)); 325 } else if (Saltlen == -2) 326 M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931); 327 if (!EVP_SignInit_ex(&ctx, dgst, NULL)) 328 goto error; 329 if (!EVP_SignUpdate(&ctx, Msg, Msglen)) 330 goto error; 331 if (!EVP_SignFinal(&ctx, sigbuf, (unsigned int *)&siglen, &pk)) 332 goto error; 333 334 EVP_MD_CTX_cleanup(&ctx); 335 336 fputs("S = ", out); 337 338 for (i = 0; i < siglen; i++) 339 fprintf(out, "%02X", sigbuf[i]); 340 341 fputs("\n", out); 342 343 ret = 1; 344 345 error: 346 347 return ret; 348} 349#endif 350