/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* This file contains RSA helper routines common to
* the PKCS11 soft token code and the kernel RSA code.
*/
#include <bignum.h>
#ifdef _KERNEL
#else
#include <strings.h>
#include <cryptoutil.h>
#endif
#include "rsa_impl.h"
/*
* DER encoding T of the DigestInfo values for MD5, SHA1, and SHA2
* from PKCS#1 v2.1: RSA Cryptography Standard Section 9.2 Note 1
*
* MD5: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H
* SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H
* SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
* SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H.
* SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H.
*
* Where H is the digested output from MD5 or SHA1. We define the constant
* byte array (the prefix) here and use it rather than doing the DER
* encoding of the OID in a separate routine.
*/
0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
0x04, 0x10};
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14};
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
0x00, 0x04, 0x20};
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
0x00, 0x04, 0x30};
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
0x00, 0x04, 0x40};
static CK_RV
{
switch (err) {
case BIG_OK:
return (CKR_OK);
case BIG_NO_MEM:
return (CKR_HOST_MEMORY);
case BIG_NO_RANDOM:
return (CKR_DEVICE_ERROR);
case BIG_INVALID_ARGS:
return (CKR_ARGUMENTS_BAD);
case BIG_DIV_BY_0:
default:
return (CKR_GENERAL_ERROR);
}
}
/* psize and qsize are in bits */
static BIG_ERR_CODE
{
return (err);
goto ret1;
goto ret2;
goto ret3;
goto ret4;
goto ret5;
goto ret6;
goto ret7;
goto ret8;
goto ret9;
goto ret10;
return (BIG_OK);
ret9:
ret8:
ret7:
ret6:
ret5:
big_finish(&(key->e));
ret4:
big_finish(&(key->d));
ret3:
big_finish(&(key->n));
ret2:
big_finish(&(key->q));
ret1:
big_finish(&(key->p));
return (err);
}
static void
{
big_finish(&(key->e));
big_finish(&(key->d));
big_finish(&(key->n));
big_finish(&(key->q));
big_finish(&(key->p));
}
/*
* Generate RSA key
*/
static CK_RV
{
BIGNUM a, b, c, d, e, f, g, h;
/*
* Note: It is not really necessary to compute e, it is in pubexp:
* (void) big_copy(&(key->e), pubexp);
*/
a.malloced = 0;
b.malloced = 0;
c.malloced = 0;
d.malloced = 0;
e.malloced = 0;
f.malloced = 0;
g.malloced = 0;
h.malloced = 0;
big_finish(&h);
big_finish(&g);
big_finish(&f);
big_finish(&e);
big_finish(&d);
big_finish(&c);
big_finish(&b);
big_finish(&a);
return (CKR_HOST_MEMORY);
}
#ifdef _KERNEL
#else
#endif
}
goto ret;
}
goto ret;
}
/* b now contains the potential prime p */
(void) big_sub_pos(&a, &b, &big_One);
goto ret;
}
if (big_cmp_abs(&f, &big_One) != 0) {
goto nextp;
}
goto ret;
}
if (big_bitlength(&a) != qsize) {
goto nextp;
}
if (big_cmp_abs(&a, &b) == 0) {
goto nextp;
}
goto ret;
}
/* c now contains the potential prime q */
goto ret;
}
if (big_bitlength(&g) != size) {
goto nextp;
}
/* g now contains the potential modulus n */
(void) big_sub_pos(&a, &b, &big_One);
(void) big_sub_pos(&d, &c, &big_One);
goto ret;
}
goto ret;
}
if (big_cmp_abs(&f, &big_One) != 0) {
goto nextq;
} else {
}
if (d.sign == -1) {
goto ret;
}
}
goto ret;
}
if (f.sign == -1) {
goto ret;
}
}
goto ret;
}
goto ret;
}
/* pairwise consistency check: decrypt and encrypt restores value */
goto ret;
}
goto ret;
}
goto ret;
}
goto ret;
}
if (big_cmp_abs(&b, &h) != 0) {
/* this should not happen */
goto ret1;
} else {
}
ret:
ret1:
big_finish(&h);
big_finish(&g);
big_finish(&f);
big_finish(&e);
big_finish(&d);
big_finish(&c);
big_finish(&b);
big_finish(&a);
return (rv);
}
{
/*
* NOTE: Whomever originally wrote this function swapped p and q.
* This table shows the mapping between name convention used here
* versus what is used in most texts that describe RSA key generation.
* This function: Standard convention:
* -------------- --------------------
* modulus, n -same-
* prime 1, q prime 1, p
* prime 2, p prime 2, q
* private exponent, d -same-
* public exponent, e -same-
* exponent 1, d mod (q-1) d mod (p-1)
* exponent 2, d mod (p-1) d mod (q-1)
* coefficient, p^-1 mod q q^-1 mod p
*
* Also notice the struct member for coefficient is named .pinvmodq
* rather than .qinvmodp, reflecting the switch.
*
* The code here wasn't unswapped, because "it works". Further,
* p and q are interchangeable as long as exponent 1 and 2 and
* the coefficient are kept straight too. This note is here to
* make the reader aware of the switcheroo.
*/
return (CKR_ARGUMENTS_BAD);
/* Must have modulus bits set */
if (bkey->modulus_bits == 0)
return (CKR_ARGUMENTS_BAD);
/* Must have public exponent set */
return (CKR_ARGUMENTS_BAD);
/* Note: modulus_bits may not be same as (8 * sizeof (modulus)) */
/* Modulus length needs to be between min key size and max key size. */
if ((modulus_bytes < MIN_RSA_KEYLENGTH_IN_BYTES) ||
return (CKR_KEY_SIZE_RANGE);
}
/*
* Initialize the RSA key.
*/
BIG_OK) {
return (CKR_HOST_MEMORY);
}
/* Create a public exponent in bignum format. */
if (big_init(&public_exponent,
goto clean1;
}
/* Generate RSA key pair. */
goto clean1;
}
/* modulus_bytes = rsakey.n.len * (int)sizeof (BIG_CHUNK_TYPE); */
bkey->expo1_bytes =
bkey->expo1_bytes);
bkey->expo2_bytes =
bkey->coeff_bytes =
return (rv);
}
/*
* RSA encrypt operation
*/
{
return (CKR_ARGUMENTS_BAD);
/* Must have modulus and public exponent set */
return (CKR_ARGUMENTS_BAD);
/* Note: modulus_bits may not be same as (8 * sizeof (modulus)) */
return (CKR_KEY_SIZE_RANGE);
}
/* psize and qsize for RSA_key_init is in bits. */
BIG_OK) {
return (CKR_HOST_MEMORY);
}
/* Size for big_init is in BIG_CHUNK_TYPE words. */
goto clean2;
}
/* Convert public exponent and modulus to big integer format. */
goto clean3;
}
/* Perform RSA computation on big integer input data. */
BIG_OK) {
goto clean3;
}
/* Convert the big integer output data to octet string. */
big_finish(&msg);
return (rv);
}
/*
* RSA decrypt operation
*/
{
return (CKR_ARGUMENTS_BAD);
/* Must have modulus, prime1, prime2, expo1, expo2, and coeff set */
return (CKR_ARGUMENTS_BAD);
/* Note: modulus_bits may not be same as (8 * sizeof (modulus)) */
/* psize and qsize for RSA_key_init is in bits. */
return (CKR_HOST_MEMORY);
}
/* Size for big_init is in BIG_CHUNK_TYPE words. */
goto clean3;
}
/* Convert octet string input data to big integer format. */
/* Convert octet string modulus to big integer format. */
goto clean4;
}
/* Convert the rest of private key attributes to big integer format. */
goto clean4;
}
/* Perform RSA computation on big integer input data. */
goto clean4;
}
/* Convert the big integer output data to octet string. */
big_finish(&msg);
return (rv);
}