1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * RSA low level APIs are deprecated for public use, but still ok for 12e1051a39Sopenharmony_ci * internal use. 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#include <stdio.h> 17e1051a39Sopenharmony_ci#include <string.h> 18e1051a39Sopenharmony_ci#include <time.h> 19e1051a39Sopenharmony_ci#include <openssl/err.h> 20e1051a39Sopenharmony_ci#include <openssl/bn.h> 21e1051a39Sopenharmony_ci#include "rsa_local.h" 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_ci/* X9.31 RSA key derivation and generation */ 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ciint RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, 26e1051a39Sopenharmony_ci BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2, 27e1051a39Sopenharmony_ci const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2, 28e1051a39Sopenharmony_ci const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb) 29e1051a39Sopenharmony_ci{ 30e1051a39Sopenharmony_ci BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL; 31e1051a39Sopenharmony_ci BN_CTX *ctx = NULL, *ctx2 = NULL; 32e1051a39Sopenharmony_ci int ret = 0; 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ci if (!rsa) 35e1051a39Sopenharmony_ci goto err; 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci ctx = BN_CTX_new(); 38e1051a39Sopenharmony_ci if (ctx == NULL) 39e1051a39Sopenharmony_ci goto err; 40e1051a39Sopenharmony_ci BN_CTX_start(ctx); 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci r0 = BN_CTX_get(ctx); 43e1051a39Sopenharmony_ci r1 = BN_CTX_get(ctx); 44e1051a39Sopenharmony_ci r2 = BN_CTX_get(ctx); 45e1051a39Sopenharmony_ci r3 = BN_CTX_get(ctx); 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_ci if (r3 == NULL) 48e1051a39Sopenharmony_ci goto err; 49e1051a39Sopenharmony_ci if (!rsa->e) { 50e1051a39Sopenharmony_ci rsa->e = BN_dup(e); 51e1051a39Sopenharmony_ci if (!rsa->e) 52e1051a39Sopenharmony_ci goto err; 53e1051a39Sopenharmony_ci } else { 54e1051a39Sopenharmony_ci e = rsa->e; 55e1051a39Sopenharmony_ci } 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_ci /* 58e1051a39Sopenharmony_ci * If not all parameters present only calculate what we can. This allows 59e1051a39Sopenharmony_ci * test programs to output selective parameters. 60e1051a39Sopenharmony_ci */ 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci if (Xp && rsa->p == NULL) { 63e1051a39Sopenharmony_ci rsa->p = BN_new(); 64e1051a39Sopenharmony_ci if (rsa->p == NULL) 65e1051a39Sopenharmony_ci goto err; 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci if (!BN_X931_derive_prime_ex(rsa->p, p1, p2, 68e1051a39Sopenharmony_ci Xp, Xp1, Xp2, e, ctx, cb)) 69e1051a39Sopenharmony_ci goto err; 70e1051a39Sopenharmony_ci } 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci if (Xq && rsa->q == NULL) { 73e1051a39Sopenharmony_ci rsa->q = BN_new(); 74e1051a39Sopenharmony_ci if (rsa->q == NULL) 75e1051a39Sopenharmony_ci goto err; 76e1051a39Sopenharmony_ci if (!BN_X931_derive_prime_ex(rsa->q, q1, q2, 77e1051a39Sopenharmony_ci Xq, Xq1, Xq2, e, ctx, cb)) 78e1051a39Sopenharmony_ci goto err; 79e1051a39Sopenharmony_ci } 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci if (rsa->p == NULL || rsa->q == NULL) { 82e1051a39Sopenharmony_ci BN_CTX_end(ctx); 83e1051a39Sopenharmony_ci BN_CTX_free(ctx); 84e1051a39Sopenharmony_ci return 2; 85e1051a39Sopenharmony_ci } 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci /* 88e1051a39Sopenharmony_ci * Since both primes are set we can now calculate all remaining 89e1051a39Sopenharmony_ci * components. 90e1051a39Sopenharmony_ci */ 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_ci /* calculate n */ 93e1051a39Sopenharmony_ci rsa->n = BN_new(); 94e1051a39Sopenharmony_ci if (rsa->n == NULL) 95e1051a39Sopenharmony_ci goto err; 96e1051a39Sopenharmony_ci if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx)) 97e1051a39Sopenharmony_ci goto err; 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci /* calculate d */ 100e1051a39Sopenharmony_ci if (!BN_sub(r1, rsa->p, BN_value_one())) 101e1051a39Sopenharmony_ci goto err; /* p-1 */ 102e1051a39Sopenharmony_ci if (!BN_sub(r2, rsa->q, BN_value_one())) 103e1051a39Sopenharmony_ci goto err; /* q-1 */ 104e1051a39Sopenharmony_ci if (!BN_mul(r0, r1, r2, ctx)) 105e1051a39Sopenharmony_ci goto err; /* (p-1)(q-1) */ 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci if (!BN_gcd(r3, r1, r2, ctx)) 108e1051a39Sopenharmony_ci goto err; 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci if (!BN_div(r0, NULL, r0, r3, ctx)) 111e1051a39Sopenharmony_ci goto err; /* LCM((p-1)(q-1)) */ 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci ctx2 = BN_CTX_new(); 114e1051a39Sopenharmony_ci if (ctx2 == NULL) 115e1051a39Sopenharmony_ci goto err; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci rsa->d = BN_mod_inverse(NULL, rsa->e, r0, ctx2); /* d */ 118e1051a39Sopenharmony_ci if (rsa->d == NULL) 119e1051a39Sopenharmony_ci goto err; 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ci /* calculate d mod (p-1) */ 122e1051a39Sopenharmony_ci rsa->dmp1 = BN_new(); 123e1051a39Sopenharmony_ci if (rsa->dmp1 == NULL) 124e1051a39Sopenharmony_ci goto err; 125e1051a39Sopenharmony_ci if (!BN_mod(rsa->dmp1, rsa->d, r1, ctx)) 126e1051a39Sopenharmony_ci goto err; 127e1051a39Sopenharmony_ci 128e1051a39Sopenharmony_ci /* calculate d mod (q-1) */ 129e1051a39Sopenharmony_ci rsa->dmq1 = BN_new(); 130e1051a39Sopenharmony_ci if (rsa->dmq1 == NULL) 131e1051a39Sopenharmony_ci goto err; 132e1051a39Sopenharmony_ci if (!BN_mod(rsa->dmq1, rsa->d, r2, ctx)) 133e1051a39Sopenharmony_ci goto err; 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci /* calculate inverse of q mod p */ 136e1051a39Sopenharmony_ci rsa->iqmp = BN_mod_inverse(NULL, rsa->q, rsa->p, ctx2); 137e1051a39Sopenharmony_ci if (rsa->iqmp == NULL) 138e1051a39Sopenharmony_ci goto err; 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci rsa->dirty_cnt++; 141e1051a39Sopenharmony_ci ret = 1; 142e1051a39Sopenharmony_ci err: 143e1051a39Sopenharmony_ci BN_CTX_end(ctx); 144e1051a39Sopenharmony_ci BN_CTX_free(ctx); 145e1051a39Sopenharmony_ci BN_CTX_free(ctx2); 146e1051a39Sopenharmony_ci 147e1051a39Sopenharmony_ci return ret; 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci} 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_ciint RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, 152e1051a39Sopenharmony_ci BN_GENCB *cb) 153e1051a39Sopenharmony_ci{ 154e1051a39Sopenharmony_ci int ok = 0; 155e1051a39Sopenharmony_ci BIGNUM *Xp = NULL, *Xq = NULL; 156e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci ctx = BN_CTX_new(); 159e1051a39Sopenharmony_ci if (ctx == NULL) 160e1051a39Sopenharmony_ci goto error; 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci BN_CTX_start(ctx); 163e1051a39Sopenharmony_ci Xp = BN_CTX_get(ctx); 164e1051a39Sopenharmony_ci Xq = BN_CTX_get(ctx); 165e1051a39Sopenharmony_ci if (Xq == NULL) 166e1051a39Sopenharmony_ci goto error; 167e1051a39Sopenharmony_ci if (!BN_X931_generate_Xpq(Xp, Xq, bits, ctx)) 168e1051a39Sopenharmony_ci goto error; 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci rsa->p = BN_new(); 171e1051a39Sopenharmony_ci rsa->q = BN_new(); 172e1051a39Sopenharmony_ci if (rsa->p == NULL || rsa->q == NULL) 173e1051a39Sopenharmony_ci goto error; 174e1051a39Sopenharmony_ci 175e1051a39Sopenharmony_ci /* Generate two primes from Xp, Xq */ 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci if (!BN_X931_generate_prime_ex(rsa->p, NULL, NULL, NULL, NULL, Xp, 178e1051a39Sopenharmony_ci e, ctx, cb)) 179e1051a39Sopenharmony_ci goto error; 180e1051a39Sopenharmony_ci 181e1051a39Sopenharmony_ci if (!BN_X931_generate_prime_ex(rsa->q, NULL, NULL, NULL, NULL, Xq, 182e1051a39Sopenharmony_ci e, ctx, cb)) 183e1051a39Sopenharmony_ci goto error; 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci /* 186e1051a39Sopenharmony_ci * Since rsa->p and rsa->q are valid this call will just derive remaining 187e1051a39Sopenharmony_ci * RSA components. 188e1051a39Sopenharmony_ci */ 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_ci if (!RSA_X931_derive_ex(rsa, NULL, NULL, NULL, NULL, 191e1051a39Sopenharmony_ci NULL, NULL, NULL, NULL, NULL, NULL, e, cb)) 192e1051a39Sopenharmony_ci goto error; 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci rsa->dirty_cnt++; 195e1051a39Sopenharmony_ci ok = 1; 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ci error: 198e1051a39Sopenharmony_ci BN_CTX_end(ctx); 199e1051a39Sopenharmony_ci BN_CTX_free(ctx); 200e1051a39Sopenharmony_ci 201e1051a39Sopenharmony_ci if (ok) 202e1051a39Sopenharmony_ci return 1; 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci return 0; 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci} 207