1193645Ssimon/* fips_rsastest.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296465Sdelphij * 2005. 5193645Ssimon */ 6193645Ssimon/* ==================================================================== 7193645Ssimon * Copyright (c) 2005 The OpenSSL Project. All rights reserved. 8193645Ssimon * 9193645Ssimon * Redistribution and use in source and binary forms, with or without 10193645Ssimon * modification, are permitted provided that the following conditions 11193645Ssimon * are met: 12193645Ssimon * 13193645Ssimon * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15193645Ssimon * 16193645Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17193645Ssimon * notice, this list of conditions and the following disclaimer in 18193645Ssimon * the documentation and/or other materials provided with the 19193645Ssimon * distribution. 20193645Ssimon * 21193645Ssimon * 3. All advertising materials mentioning features or use of this 22193645Ssimon * software must display the following acknowledgment: 23193645Ssimon * "This product includes software developed by the OpenSSL Project 24193645Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25193645Ssimon * 26193645Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27193645Ssimon * endorse or promote products derived from this software without 28193645Ssimon * prior written permission. For written permission, please contact 29193645Ssimon * licensing@OpenSSL.org. 30193645Ssimon * 31193645Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32193645Ssimon * nor may "OpenSSL" appear in their names without prior written 33193645Ssimon * permission of the OpenSSL Project. 34193645Ssimon * 35193645Ssimon * 6. Redistributions of any form whatsoever must retain the following 36193645Ssimon * acknowledgment: 37193645Ssimon * "This product includes software developed by the OpenSSL Project 38193645Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39193645Ssimon * 40193645Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41193645Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42193645Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43193645Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44193645Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45193645Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46193645Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47193645Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48193645Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49193645Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50193645Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51193645Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52193645Ssimon * ==================================================================== 53193645Ssimon * 54193645Ssimon * This product includes cryptographic software written by Eric Young 55193645Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 56193645Ssimon * Hudson (tjh@cryptsoft.com). 57193645Ssimon * 58193645Ssimon */ 59193645Ssimon 60193645Ssimon#include <stdio.h> 61193645Ssimon#include <ctype.h> 62193645Ssimon#include <string.h> 63193645Ssimon#include <openssl/bio.h> 64193645Ssimon#include <openssl/evp.h> 65193645Ssimon#include <openssl/hmac.h> 66193645Ssimon#include <openssl/err.h> 67193645Ssimon#include <openssl/bn.h> 68193645Ssimon#include <openssl/x509v3.h> 69193645Ssimon 70193645Ssimon#ifndef OPENSSL_FIPS 71193645Ssimon 72193645Ssimonint main(int argc, char *argv[]) 73193645Ssimon{ 74193645Ssimon printf("No FIPS RSA support\n"); 75296465Sdelphij return (0); 76193645Ssimon} 77193645Ssimon 78193645Ssimon#else 79193645Ssimon 80296465Sdelphij# include <openssl/rsa.h> 81296465Sdelphij# include "fips_utl.h" 82193645Ssimon 83193645Ssimonstatic int rsa_stest(FILE *out, FILE *in, int Saltlen); 84193645Ssimonstatic int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst, 85296465Sdelphij unsigned char *Msg, long Msglen, int Saltlen); 86193645Ssimon 87193645Ssimonint main(int argc, char **argv) 88296465Sdelphij{ 89296465Sdelphij FILE *in = NULL, *out = NULL; 90193645Ssimon 91296465Sdelphij int ret = 1, Saltlen = -1; 92193645Ssimon 93296465Sdelphij if (!FIPS_mode_set(1)) { 94296465Sdelphij do_print_errors(); 95296465Sdelphij goto end; 96296465Sdelphij } 97193645Ssimon 98296465Sdelphij if ((argc > 2) && !strcmp("-saltlen", argv[1])) { 99296465Sdelphij Saltlen = atoi(argv[2]); 100296465Sdelphij if (Saltlen < 0) { 101296465Sdelphij fprintf(stderr, "FATAL: Invalid salt length\n"); 102296465Sdelphij goto end; 103296465Sdelphij } 104296465Sdelphij argc -= 2; 105296465Sdelphij argv += 2; 106296465Sdelphij } else if ((argc > 1) && !strcmp("-x931", argv[1])) { 107296465Sdelphij Saltlen = -2; 108296465Sdelphij argc--; 109296465Sdelphij argv++; 110296465Sdelphij } 111193645Ssimon 112296465Sdelphij if (argc == 1) 113296465Sdelphij in = stdin; 114296465Sdelphij else 115296465Sdelphij in = fopen(argv[1], "r"); 116193645Ssimon 117296465Sdelphij if (argc < 2) 118296465Sdelphij out = stdout; 119296465Sdelphij else 120296465Sdelphij out = fopen(argv[2], "w"); 121193645Ssimon 122296465Sdelphij if (!in) { 123296465Sdelphij fprintf(stderr, "FATAL input initialization error\n"); 124296465Sdelphij goto end; 125296465Sdelphij } 126193645Ssimon 127296465Sdelphij if (!out) { 128296465Sdelphij fprintf(stderr, "FATAL output initialization error\n"); 129296465Sdelphij goto end; 130296465Sdelphij } 131193645Ssimon 132296465Sdelphij if (!rsa_stest(out, in, Saltlen)) { 133296465Sdelphij fprintf(stderr, "FATAL RSASTEST file processing error\n"); 134296465Sdelphij goto end; 135296465Sdelphij } else 136296465Sdelphij ret = 0; 137193645Ssimon 138296465Sdelphij end: 139193645Ssimon 140296465Sdelphij if (ret) 141296465Sdelphij do_print_errors(); 142193645Ssimon 143296465Sdelphij if (in && (in != stdin)) 144296465Sdelphij fclose(in); 145296465Sdelphij if (out && (out != stdout)) 146296465Sdelphij fclose(out); 147193645Ssimon 148296465Sdelphij return ret; 149193645Ssimon 150296465Sdelphij} 151193645Ssimon 152296465Sdelphij# define RSA_TEST_MAXLINELEN 10240 153193645Ssimon 154193645Ssimonint rsa_stest(FILE *out, FILE *in, int Saltlen) 155296465Sdelphij{ 156296465Sdelphij char *linebuf, *olinebuf, *p, *q; 157296465Sdelphij char *keyword, *value; 158296465Sdelphij RSA *rsa = NULL; 159296465Sdelphij const EVP_MD *dgst = NULL; 160296465Sdelphij unsigned char *Msg = NULL; 161296465Sdelphij long Msglen = -1; 162296465Sdelphij int keylen = -1, current_keylen = -1; 163296465Sdelphij int ret = 0; 164296465Sdelphij int lnum = 0; 165193645Ssimon 166296465Sdelphij olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 167296465Sdelphij linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 168193645Ssimon 169296465Sdelphij if (!linebuf || !olinebuf) 170296465Sdelphij goto error; 171193645Ssimon 172296465Sdelphij while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) { 173296465Sdelphij lnum++; 174296465Sdelphij strcpy(linebuf, olinebuf); 175296465Sdelphij keyword = linebuf; 176296465Sdelphij /* Skip leading space */ 177296465Sdelphij while (isspace((unsigned char)*keyword)) 178296465Sdelphij keyword++; 179193645Ssimon 180296465Sdelphij /* Look for = sign */ 181296465Sdelphij p = strchr(linebuf, '='); 182193645Ssimon 183296465Sdelphij /* If no = just copy */ 184296465Sdelphij if (!p) { 185296465Sdelphij if (fputs(olinebuf, out) < 0) 186296465Sdelphij goto error; 187296465Sdelphij continue; 188296465Sdelphij } 189193645Ssimon 190296465Sdelphij q = p - 1; 191193645Ssimon 192296465Sdelphij /* Remove trailing space */ 193296465Sdelphij while (isspace((unsigned char)*q)) 194296465Sdelphij *q-- = 0; 195193645Ssimon 196296465Sdelphij *p = 0; 197296465Sdelphij value = p + 1; 198193645Ssimon 199296465Sdelphij /* Remove leading space from value */ 200296465Sdelphij while (isspace((unsigned char)*value)) 201296465Sdelphij value++; 202193645Ssimon 203296465Sdelphij /* Remove trailing space from value */ 204296465Sdelphij p = value + strlen(value) - 1; 205193645Ssimon 206296465Sdelphij while (*p == '\n' || isspace((unsigned char)*p)) 207296465Sdelphij *p-- = 0; 208193645Ssimon 209296465Sdelphij /* Look for [mod = XXX] for key length */ 210193645Ssimon 211296465Sdelphij if (!strcmp(keyword, "[mod")) { 212296465Sdelphij p = value + strlen(value) - 1; 213296465Sdelphij if (*p != ']') 214296465Sdelphij goto parse_error; 215296465Sdelphij *p = 0; 216296465Sdelphij keylen = atoi(value); 217296465Sdelphij if (keylen < 0) 218296465Sdelphij goto parse_error; 219296465Sdelphij } else if (!strcmp(keyword, "SHAAlg")) { 220296465Sdelphij if (!strcmp(value, "SHA1")) 221296465Sdelphij dgst = EVP_sha1(); 222296465Sdelphij else if (!strcmp(value, "SHA224")) 223296465Sdelphij dgst = EVP_sha224(); 224296465Sdelphij else if (!strcmp(value, "SHA256")) 225296465Sdelphij dgst = EVP_sha256(); 226296465Sdelphij else if (!strcmp(value, "SHA384")) 227296465Sdelphij dgst = EVP_sha384(); 228296465Sdelphij else if (!strcmp(value, "SHA512")) 229296465Sdelphij dgst = EVP_sha512(); 230296465Sdelphij else { 231296465Sdelphij fprintf(stderr, 232296465Sdelphij "FATAL: unsupported algorithm \"%s\"\n", value); 233296465Sdelphij goto parse_error; 234296465Sdelphij } 235296465Sdelphij } else if (!strcmp(keyword, "Msg")) { 236296465Sdelphij if (Msg) 237296465Sdelphij goto parse_error; 238296465Sdelphij if (strlen(value) & 1) 239296465Sdelphij *(--value) = '0'; 240296465Sdelphij Msg = hex2bin_m(value, &Msglen); 241296465Sdelphij if (!Msg) 242296465Sdelphij goto parse_error; 243296465Sdelphij } 244193645Ssimon 245296465Sdelphij fputs(olinebuf, out); 246193645Ssimon 247296465Sdelphij /* 248296465Sdelphij * If key length has changed, generate and output public key 249296465Sdelphij * components of new RSA private key. 250296465Sdelphij */ 251193645Ssimon 252296465Sdelphij if (keylen != current_keylen) { 253296465Sdelphij BIGNUM *bn_e; 254296465Sdelphij if (rsa) 255296465Sdelphij FIPS_rsa_free(rsa); 256296465Sdelphij rsa = FIPS_rsa_new(); 257296465Sdelphij if (!rsa) 258296465Sdelphij goto error; 259296465Sdelphij bn_e = BN_new(); 260296465Sdelphij if (!bn_e || !BN_set_word(bn_e, 0x1001)) 261296465Sdelphij goto error; 262296465Sdelphij if (!RSA_X931_generate_key_ex(rsa, keylen, bn_e, NULL)) 263296465Sdelphij goto error; 264296465Sdelphij BN_free(bn_e); 265296465Sdelphij fputs("n = ", out); 266296465Sdelphij do_bn_print(out, rsa->n); 267296465Sdelphij fputs("\ne = ", out); 268296465Sdelphij do_bn_print(out, rsa->e); 269296465Sdelphij fputs("\n", out); 270296465Sdelphij current_keylen = keylen; 271296465Sdelphij } 272193645Ssimon 273296465Sdelphij if (Msg && dgst) { 274296465Sdelphij if (!rsa_printsig(out, rsa, dgst, Msg, Msglen, Saltlen)) 275296465Sdelphij goto error; 276296465Sdelphij OPENSSL_free(Msg); 277296465Sdelphij Msg = NULL; 278296465Sdelphij } 279193645Ssimon 280296465Sdelphij } 281193645Ssimon 282296465Sdelphij ret = 1; 283193645Ssimon 284296465Sdelphij error: 285193645Ssimon 286296465Sdelphij if (olinebuf) 287296465Sdelphij OPENSSL_free(olinebuf); 288296465Sdelphij if (linebuf) 289296465Sdelphij OPENSSL_free(linebuf); 290296465Sdelphij if (rsa) 291296465Sdelphij FIPS_rsa_free(rsa); 292193645Ssimon 293296465Sdelphij return ret; 294193645Ssimon 295296465Sdelphij parse_error: 296193645Ssimon 297296465Sdelphij fprintf(stderr, "FATAL parse error processing line %d\n", lnum); 298193645Ssimon 299296465Sdelphij goto error; 300193645Ssimon 301296465Sdelphij} 302193645Ssimon 303193645Ssimonstatic int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst, 304296465Sdelphij unsigned char *Msg, long Msglen, int Saltlen) 305296465Sdelphij{ 306296465Sdelphij int ret = 0; 307296465Sdelphij unsigned char *sigbuf = NULL; 308296465Sdelphij int i, siglen; 309296465Sdelphij /* EVP_PKEY structure */ 310296465Sdelphij EVP_PKEY pk; 311296465Sdelphij EVP_MD_CTX ctx; 312296465Sdelphij pk.type = EVP_PKEY_RSA; 313296465Sdelphij pk.pkey.rsa = rsa; 314193645Ssimon 315296465Sdelphij siglen = RSA_size(rsa); 316296465Sdelphij sigbuf = OPENSSL_malloc(siglen); 317296465Sdelphij if (!sigbuf) 318296465Sdelphij goto error; 319193645Ssimon 320296465Sdelphij EVP_MD_CTX_init(&ctx); 321193645Ssimon 322296465Sdelphij if (Saltlen >= 0) { 323296465Sdelphij M_EVP_MD_CTX_set_flags(&ctx, 324296465Sdelphij EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16)); 325296465Sdelphij } else if (Saltlen == -2) 326296465Sdelphij M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931); 327296465Sdelphij if (!EVP_SignInit_ex(&ctx, dgst, NULL)) 328296465Sdelphij goto error; 329296465Sdelphij if (!EVP_SignUpdate(&ctx, Msg, Msglen)) 330296465Sdelphij goto error; 331296465Sdelphij if (!EVP_SignFinal(&ctx, sigbuf, (unsigned int *)&siglen, &pk)) 332296465Sdelphij goto error; 333193645Ssimon 334296465Sdelphij EVP_MD_CTX_cleanup(&ctx); 335193645Ssimon 336296465Sdelphij fputs("S = ", out); 337193645Ssimon 338296465Sdelphij for (i = 0; i < siglen; i++) 339296465Sdelphij fprintf(out, "%02X", sigbuf[i]); 340193645Ssimon 341296465Sdelphij fputs("\n", out); 342193645Ssimon 343296465Sdelphij ret = 1; 344193645Ssimon 345296465Sdelphij error: 346193645Ssimon 347296465Sdelphij return ret; 348296465Sdelphij} 349193645Ssimon#endif 350