1193645Ssimon/* fips_rsavtest.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/x509v3.h> 68193645Ssimon#include <openssl/bn.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> 81205128Ssimon 82296465Sdelphij# include "fips_utl.h" 83193645Ssimon 84193645Ssimonint rsa_test(FILE *out, FILE *in, int saltlen); 85193645Ssimonstatic int rsa_printver(FILE *out, 86296465Sdelphij BIGNUM *n, BIGNUM *e, 87296465Sdelphij const EVP_MD *dgst, 88296465Sdelphij unsigned char *Msg, long Msglen, 89296465Sdelphij unsigned char *S, long Slen, int Saltlen); 90193645Ssimon 91193645Ssimonint main(int argc, char **argv) 92296465Sdelphij{ 93296465Sdelphij FILE *in = NULL, *out = NULL; 94193645Ssimon 95296465Sdelphij int ret = 1; 96296465Sdelphij int Saltlen = -1; 97193645Ssimon 98296465Sdelphij if (!FIPS_mode_set(1)) { 99296465Sdelphij do_print_errors(); 100296465Sdelphij goto end; 101296465Sdelphij } 102193645Ssimon 103296465Sdelphij if ((argc > 2) && !strcmp("-saltlen", argv[1])) { 104296465Sdelphij Saltlen = atoi(argv[2]); 105296465Sdelphij if (Saltlen < 0) { 106296465Sdelphij fprintf(stderr, "FATAL: Invalid salt length\n"); 107296465Sdelphij goto end; 108296465Sdelphij } 109296465Sdelphij argc -= 2; 110296465Sdelphij argv += 2; 111296465Sdelphij } else if ((argc > 1) && !strcmp("-x931", argv[1])) { 112296465Sdelphij Saltlen = -2; 113296465Sdelphij argc--; 114296465Sdelphij argv++; 115296465Sdelphij } 116193645Ssimon 117296465Sdelphij if (argc == 1) 118296465Sdelphij in = stdin; 119296465Sdelphij else 120296465Sdelphij in = fopen(argv[1], "r"); 121193645Ssimon 122296465Sdelphij if (argc < 2) 123296465Sdelphij out = stdout; 124296465Sdelphij else 125296465Sdelphij out = fopen(argv[2], "w"); 126193645Ssimon 127296465Sdelphij if (!in) { 128296465Sdelphij fprintf(stderr, "FATAL input initialization error\n"); 129296465Sdelphij goto end; 130296465Sdelphij } 131193645Ssimon 132296465Sdelphij if (!out) { 133296465Sdelphij fprintf(stderr, "FATAL output initialization error\n"); 134296465Sdelphij goto end; 135296465Sdelphij } 136193645Ssimon 137296465Sdelphij if (!rsa_test(out, in, Saltlen)) { 138296465Sdelphij fprintf(stderr, "FATAL RSAVTEST file processing error\n"); 139296465Sdelphij goto end; 140296465Sdelphij } else 141296465Sdelphij ret = 0; 142193645Ssimon 143296465Sdelphij end: 144193645Ssimon 145296465Sdelphij if (ret) 146296465Sdelphij do_print_errors(); 147193645Ssimon 148296465Sdelphij if (in && (in != stdin)) 149296465Sdelphij fclose(in); 150296465Sdelphij if (out && (out != stdout)) 151296465Sdelphij fclose(out); 152193645Ssimon 153296465Sdelphij return ret; 154193645Ssimon 155296465Sdelphij} 156193645Ssimon 157296465Sdelphij# define RSA_TEST_MAXLINELEN 10240 158193645Ssimon 159193645Ssimonint rsa_test(FILE *out, FILE *in, int Saltlen) 160296465Sdelphij{ 161296465Sdelphij char *linebuf, *olinebuf, *p, *q; 162296465Sdelphij char *keyword, *value; 163296465Sdelphij const EVP_MD *dgst = NULL; 164296465Sdelphij BIGNUM *n = NULL, *e = NULL; 165296465Sdelphij unsigned char *Msg = NULL, *S = NULL; 166296465Sdelphij long Msglen, Slen; 167296465Sdelphij int ret = 0; 168296465Sdelphij int lnum = 0; 169193645Ssimon 170296465Sdelphij olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 171296465Sdelphij linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN); 172193645Ssimon 173296465Sdelphij if (!linebuf || !olinebuf) 174296465Sdelphij goto error; 175193645Ssimon 176296465Sdelphij while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) { 177296465Sdelphij lnum++; 178296465Sdelphij strcpy(linebuf, olinebuf); 179296465Sdelphij keyword = linebuf; 180296465Sdelphij /* Skip leading space */ 181296465Sdelphij while (isspace((unsigned char)*keyword)) 182296465Sdelphij keyword++; 183193645Ssimon 184296465Sdelphij /* Look for = sign */ 185296465Sdelphij p = strchr(linebuf, '='); 186193645Ssimon 187296465Sdelphij /* 188296465Sdelphij * If no = or starts with [ (for [foo = bar] line) just copy 189296465Sdelphij */ 190296465Sdelphij if (!p || *keyword == '[') { 191296465Sdelphij if (fputs(olinebuf, out) < 0) 192296465Sdelphij goto error; 193296465Sdelphij continue; 194296465Sdelphij } 195193645Ssimon 196296465Sdelphij q = p - 1; 197193645Ssimon 198296465Sdelphij /* Remove trailing space */ 199296465Sdelphij while (isspace((unsigned char)*q)) 200296465Sdelphij *q-- = 0; 201193645Ssimon 202296465Sdelphij *p = 0; 203296465Sdelphij value = p + 1; 204193645Ssimon 205296465Sdelphij /* Remove leading space from value */ 206296465Sdelphij while (isspace((unsigned char)*value)) 207296465Sdelphij value++; 208193645Ssimon 209296465Sdelphij /* Remove trailing space from value */ 210296465Sdelphij p = value + strlen(value) - 1; 211193645Ssimon 212296465Sdelphij while (*p == '\n' || isspace((unsigned char)*p)) 213296465Sdelphij *p-- = 0; 214193645Ssimon 215296465Sdelphij if (!strcmp(keyword, "n")) { 216296465Sdelphij if (!do_hex2bn(&n, value)) 217296465Sdelphij goto parse_error; 218296465Sdelphij } else if (!strcmp(keyword, "e")) { 219296465Sdelphij if (!do_hex2bn(&e, value)) 220296465Sdelphij goto parse_error; 221296465Sdelphij } else if (!strcmp(keyword, "SHAAlg")) { 222296465Sdelphij if (!strcmp(value, "SHA1")) 223296465Sdelphij dgst = EVP_sha1(); 224296465Sdelphij else if (!strcmp(value, "SHA224")) 225296465Sdelphij dgst = EVP_sha224(); 226296465Sdelphij else if (!strcmp(value, "SHA256")) 227296465Sdelphij dgst = EVP_sha256(); 228296465Sdelphij else if (!strcmp(value, "SHA384")) 229296465Sdelphij dgst = EVP_sha384(); 230296465Sdelphij else if (!strcmp(value, "SHA512")) 231296465Sdelphij dgst = EVP_sha512(); 232296465Sdelphij else { 233296465Sdelphij fprintf(stderr, 234296465Sdelphij "FATAL: unsupported algorithm \"%s\"\n", value); 235296465Sdelphij goto parse_error; 236296465Sdelphij } 237296465Sdelphij } else if (!strcmp(keyword, "Msg")) { 238296465Sdelphij if (Msg) 239296465Sdelphij goto parse_error; 240296465Sdelphij if (strlen(value) & 1) 241296465Sdelphij *(--value) = '0'; 242296465Sdelphij Msg = hex2bin_m(value, &Msglen); 243296465Sdelphij if (!Msg) 244296465Sdelphij goto parse_error; 245296465Sdelphij } else if (!strcmp(keyword, "S")) { 246296465Sdelphij if (S) 247296465Sdelphij goto parse_error; 248296465Sdelphij if (strlen(value) & 1) 249296465Sdelphij *(--value) = '0'; 250296465Sdelphij S = hex2bin_m(value, &Slen); 251296465Sdelphij if (!S) 252296465Sdelphij goto parse_error; 253296465Sdelphij } else if (!strcmp(keyword, "Result")) 254296465Sdelphij continue; 255296465Sdelphij else 256296465Sdelphij goto parse_error; 257193645Ssimon 258296465Sdelphij fputs(olinebuf, out); 259193645Ssimon 260296465Sdelphij if (n && e && Msg && S && dgst) { 261296465Sdelphij if (!rsa_printver(out, n, e, dgst, Msg, Msglen, S, Slen, Saltlen)) 262296465Sdelphij goto error; 263296465Sdelphij OPENSSL_free(Msg); 264296465Sdelphij Msg = NULL; 265296465Sdelphij OPENSSL_free(S); 266296465Sdelphij S = NULL; 267296465Sdelphij } 268193645Ssimon 269296465Sdelphij } 270193645Ssimon 271296465Sdelphij ret = 1; 272193645Ssimon 273296465Sdelphij error: 274193645Ssimon 275296465Sdelphij if (olinebuf) 276296465Sdelphij OPENSSL_free(olinebuf); 277296465Sdelphij if (linebuf) 278296465Sdelphij OPENSSL_free(linebuf); 279296465Sdelphij if (n) 280296465Sdelphij BN_free(n); 281296465Sdelphij if (e) 282296465Sdelphij BN_free(e); 283193645Ssimon 284296465Sdelphij return ret; 285193645Ssimon 286296465Sdelphij parse_error: 287193645Ssimon 288296465Sdelphij fprintf(stderr, "FATAL parse error processing line %d\n", lnum); 289193645Ssimon 290296465Sdelphij goto error; 291193645Ssimon 292296465Sdelphij} 293193645Ssimon 294193645Ssimonstatic int rsa_printver(FILE *out, 295296465Sdelphij BIGNUM *n, BIGNUM *e, 296296465Sdelphij const EVP_MD *dgst, 297296465Sdelphij unsigned char *Msg, long Msglen, 298296465Sdelphij unsigned char *S, long Slen, int Saltlen) 299296465Sdelphij{ 300296465Sdelphij int ret = 0, r; 301296465Sdelphij /* Setup RSA and EVP_PKEY structures */ 302296465Sdelphij RSA *rsa_pubkey = NULL; 303296465Sdelphij EVP_PKEY pk; 304296465Sdelphij EVP_MD_CTX ctx; 305296465Sdelphij unsigned char *buf = NULL; 306296465Sdelphij rsa_pubkey = FIPS_rsa_new(); 307296465Sdelphij if (!rsa_pubkey) 308296465Sdelphij goto error; 309296465Sdelphij rsa_pubkey->n = BN_dup(n); 310296465Sdelphij rsa_pubkey->e = BN_dup(e); 311296465Sdelphij if (!rsa_pubkey->n || !rsa_pubkey->e) 312296465Sdelphij goto error; 313296465Sdelphij pk.type = EVP_PKEY_RSA; 314296465Sdelphij pk.pkey.rsa = rsa_pubkey; 315193645Ssimon 316296465Sdelphij EVP_MD_CTX_init(&ctx); 317193645Ssimon 318296465Sdelphij if (Saltlen >= 0) { 319296465Sdelphij M_EVP_MD_CTX_set_flags(&ctx, 320296465Sdelphij EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16)); 321296465Sdelphij } else if (Saltlen == -2) 322296465Sdelphij M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931); 323296465Sdelphij if (!EVP_VerifyInit_ex(&ctx, dgst, NULL)) 324296465Sdelphij goto error; 325296465Sdelphij if (!EVP_VerifyUpdate(&ctx, Msg, Msglen)) 326296465Sdelphij goto error; 327193645Ssimon 328296465Sdelphij r = EVP_VerifyFinal(&ctx, S, Slen, &pk); 329193645Ssimon 330296465Sdelphij EVP_MD_CTX_cleanup(&ctx); 331193645Ssimon 332296465Sdelphij if (r < 0) 333296465Sdelphij goto error; 334296465Sdelphij ERR_clear_error(); 335193645Ssimon 336296465Sdelphij if (r == 0) 337296465Sdelphij fputs("Result = F\n", out); 338296465Sdelphij else 339296465Sdelphij fputs("Result = P\n", out); 340193645Ssimon 341296465Sdelphij ret = 1; 342193645Ssimon 343296465Sdelphij error: 344296465Sdelphij if (rsa_pubkey) 345296465Sdelphij FIPS_rsa_free(rsa_pubkey); 346296465Sdelphij if (buf) 347296465Sdelphij OPENSSL_free(buf); 348193645Ssimon 349296465Sdelphij return ret; 350296465Sdelphij} 351193645Ssimon#endif 352