Add support in pkcs11-tool and pkcs11-spy for RSA-OAEP (#1169)

* Add RSA-OAEP documentation
* Add definitions and structures needed for RSA-OAEP
* Add ability to display RSA-OAEP parameters to SPY

Closes https://github.com/OpenSC/OpenSC/issues/1170
This commit is contained in:
Mouse 2017-10-19 16:12:47 -04:00 committed by Frank Morgner
parent 391b32c378
commit e4c589639d
4 changed files with 138 additions and 11 deletions

View File

@ -75,8 +75,22 @@
<term>
<option>--hash-algorithm</option> <replaceable>mechanism</replaceable>
</term>
<listitem><para>Specify hash algorithm used with
RSA-PKCS-PSS signature. Default is SHA-1.</para></listitem>
<listitem>
<para>
Specify hash algorithm used with RSA-PKCS-PSS signature or RSA-OAEP decryption.
Allowed values are "SHA-1", "SHA256", "SHA384", "SHA512", and some tokens may
also allow "SHA224". Default is "SHA-1".
</para>
<para>
Note that the input to RSA-PKCS-PSS has to be of the size equal to
the specified hash algorithm. E.g., for SHA256 the signature input must
be exactly 32 bytes long (for mechanisms SHA256-RSA-PKCS-PSS there is no
such restriction). For RSA-OAEP, the plaintext input size mLen must be
at most keyLen - 2 - 2*hashLen. For example, for RSA 3072-bit key and
SHA384, the longest plaintext to encrypt with RSA-OAEP is (with all
sizes in bytes): 384 - 2 - 2*48 = 286, aka 286 bytes.
</para>
</listitem>
</varlistentry>
<varlistentry>
@ -226,9 +240,10 @@
</term>
<listitem><para>Use the specified Message Generation
Function (MGF) <replaceable>function</replaceable>
for RSA-PSS signatures. Supported arguments are MGF1-SHA1
for RSA-PKCS-PSS signatures or RSA-OAEP decryptions. Supported arguments are MGF1-SHA1
to MGF1-SHA512 if supported by the driver.
The default is based on the hash selection.</para></listitem>
The default is based on the hash selection.
</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -844,6 +844,26 @@ C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT
enter("C_DecryptInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
switch (pMechanism->mechanism) {
case CKM_RSA_PKCS_OAEP:
if (pMechanism->pParameter != NULL) {
CK_RSA_PKCS_OAEP_PARAMS *param =
(CK_RSA_PKCS_OAEP_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "pMechanism->pParameter->hashAlg=%s\n",
lookup_enum(MEC_T, param->hashAlg));
fprintf(spy_output, "pMechanism->pParameter->mgf=%s\n",
lookup_enum(MGF_T, param->mgf));
fprintf(spy_output, "pMechanism->pParameter->source=%lu\n", param->source);
spy_dump_string_out("pSourceData[ulSourceDalaLen]",
param->pSourceData, param->ulSourceDataLen);
} else {
fprintf(spy_output, "Parameters block for %s is empty...\n",
lookup_enum(MEC_T, pMechanism->mechanism));
}
break;
default:
break;
}
spy_dump_ulong_in("hKey", hKey);
rv = po->C_DecryptInit(hSession, pMechanism, hKey);
return retne(rv);
@ -984,6 +1004,9 @@ C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HA
lookup_enum(MGF_T, param->mgf));
fprintf(spy_output, "pMechanism->pParameter->sLen=%lu\n",
param->sLen);
} else {
fprintf(spy_output, "Parameters block for %s is empty...\n",
lookup_enum(MEC_T, pMechanism->mechanism));
}
break;
}

View File

@ -764,10 +764,20 @@ typedef struct CK_ECDH1_DERIVE_PARAMS {
unsigned char * pPublicData;
} CK_ECDH1_DERIVE_PARAMS;
typedef unsigned long CK_RSA_PKCS_OAEP_SOURCE_TYPE;
typedef struct CK_RSA_PKCS_OAEP_PARAMS {
CK_MECHANISM_TYPE hashAlg;
CK_RSA_PKCS_MGF_TYPE mgf;
CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
void *pSourceData;
unsigned long ulSourceDataLen;
} CK_RSA_PKCS_OAEP_PARAMS;
typedef struct CK_RSA_PKCS_PSS_PARAMS {
ck_mechanism_type_t hashAlg;
unsigned long mgf;
unsigned long sLen;
ck_mechanism_type_t hashAlg;
unsigned long mgf;
unsigned long sLen;
} CK_RSA_PKCS_PSS_PARAMS;
#define CKG_MGF1_SHA1 (0x00000001UL)

View File

@ -235,8 +235,8 @@ static const char *option_help[] = {
"Derive a secret key using another key and some data",
"Derive ECDHpass DER encoded pubkey for compatibility with some PKCS#11 implementations",
"Specify mechanism (use -M for a list of supported mechanisms)",
"Specify hash algorithm used with RSA-PKCS-PSS signature",
"Specify MGF (Message Generation Function) used for RSA-PSS signatures (possible values are MGF1-SHA1 to MGF1-SHA512)",
"Specify hash algorithm used with RSA-PKCS-PSS signature and RSA-PKCS-OAEP decryption",
"Specify MGF (Message Generation Function) used for RSA-PSS signature and RSA-OAEP decryption (possible values are MGF1-SHA1 to MGF1-SHA512)",
"Specify how many bytes should be used for salt in RSA-PSS signatures (default is digest size)",
"Log into the token first",
@ -1692,6 +1692,9 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
pss_params.hashAlg = opt_hash_alg;
switch (opt_hash_alg) {
case CKM_SHA224:
pss_params.mgf = CKG_MGF1_SHA224;
break;
case CKM_SHA256:
pss_params.mgf = CKG_MGF1_SHA256;
break;
@ -1715,6 +1718,11 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
pss_params.mgf = CKG_MGF1_SHA1;
break;
case CKM_SHA224_RSA_PKCS_PSS:
pss_params.hashAlg = CKM_SHA224;
pss_params.mgf = CKG_MGF1_SHA224;
break;
case CKM_SHA256_RSA_PKCS_PSS:
pss_params.hashAlg = CKM_SHA256;
pss_params.mgf = CKG_MGF1_SHA256;
@ -1762,7 +1770,8 @@ to zero, or equal to -1 (meaning: use digest size) or to -2 \
mech.pParameter = &pss_params;
mech.ulParameterLen = sizeof(pss_params);
fprintf(stderr, "PSS parameters: hashAlg=%s, mgf=%s, salt=%lu B\n",
fprintf(stderr, "PSS parameters: hashAlg=%s, mgf=%s, salt_len=%lu B\n",
p11_mechanism_to_name(pss_params.hashAlg),
p11_mgf_to_name(pss_params.mgf),
pss_params.sLen);
@ -1777,6 +1786,10 @@ to zero, or equal to -1 (meaning: use digest size) or to -2 \
if (r < 0)
util_fatal("Cannot read from %s: %m", opt_input);
if (opt_mechanism == CKM_RSA_PKCS_PSS && (unsigned long)r != hashlen)
util_fatal("For %s mechanism, message size (got %d bytes) must be equal to specified digest length (%lu)\n",
p11_mechanism_to_name(opt_mechanism), r, hashlen);
rv = CKR_CANCEL;
if (r < (int) sizeof(in_buffer)) {
rv = p11->C_SignInit(session, &mech, key);
@ -1819,7 +1832,7 @@ to zero, or equal to -1 (meaning: use digest size) or to -2 \
util_fatal("failed to open %s: %m", opt_output);
}
if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1 || opt_mechanism == CKM_ECDSA_SHA256 || opt_mechanism == CKM_ECDSA_SHA384 || opt_mechanism == CKM_ECDSA_SHA512) {
if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1 || opt_mechanism == CKM_ECDSA_SHA256 || opt_mechanism == CKM_ECDSA_SHA384 || opt_mechanism == CKM_ECDSA_SHA512 || opt_mechanism == CKM_ECDSA_SHA224) {
if (opt_sig_format && (!strcmp(opt_sig_format, "openssl") || !strcmp(opt_sig_format, "sequence"))) {
unsigned char *seq;
size_t seqlen;
@ -1849,6 +1862,7 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
unsigned char in_buffer[1024], out_buffer[1024];
CK_MECHANISM mech;
CK_RV rv;
CK_RSA_PKCS_OAEP_PARAMS oaep_params;
CK_ULONG in_len, out_len;
int fd, r;
@ -1859,6 +1873,11 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
fprintf(stderr, "Using decrypt algorithm %s\n", p11_mechanism_to_name(opt_mechanism));
memset(&mech, 0, sizeof(mech));
mech.mechanism = opt_mechanism;
oaep_params.hashAlg = 0;
if (opt_hash_alg != 0 && opt_mechanism != CKM_RSA_PKCS_OAEP)
util_fatal("The hash-algorithm is applicable only to "
"RSA-PKCS-OAEP mechanism");
if (opt_input == NULL)
fd = 0;
@ -1870,6 +1889,62 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
util_fatal("Cannot read from %s: %m", opt_input);
in_len = r;
/* set "default" MGF and hash algorithms. We can overwrite MGF later */
switch (opt_mechanism) {
case CKM_RSA_PKCS_OAEP:
oaep_params.hashAlg = opt_hash_alg;
switch (opt_hash_alg) {
case CKM_SHA224:
oaep_params.mgf = CKG_MGF1_SHA224;
break;
case CKM_SHA256:
oaep_params.mgf = CKG_MGF1_SHA256;
break;
case CKM_SHA384:
oaep_params.mgf = CKG_MGF1_SHA384;
break;
case CKM_SHA512:
oaep_params.mgf = CKG_MGF1_SHA512;
break;
default:
oaep_params.hashAlg = CKM_SHA_1;
/* fallthrough to SHA-1 default */
case CKM_SHA_1:
oaep_params.mgf = CKG_MGF1_SHA1;
break;
}
break;
case CKM_RSA_PKCS:
mech.pParameter = NULL;
mech.ulParameterLen = 0;
break;
default:
util_fatal("Mechanism %s illegal or not supported\n", p11_mechanism_to_name(opt_mechanism));
}
/* If an RSA-OAEP mechanism, it needs parameters */
if (oaep_params.hashAlg) {
if (opt_mgf != 0)
oaep_params.mgf = opt_mgf;
/* These settings are compatible with OpenSSL 1.0.2L and 1.1.0+ */
oaep_params.source = 0UL; /* empty encoding parameter (label) */
oaep_params.pSourceData = NULL; /* PKCS#11 standard: this must be NULLPTR */
oaep_params.ulSourceDataLen = 0; /* PKCS#11 standard: this must be 0 */
mech.pParameter = &oaep_params;
mech.ulParameterLen = sizeof(oaep_params);
fprintf(stderr, "OAEP parameters: hashAlg=%s, mgf=%s, source_type=%lu, source_ptr=%p, source_len=%lu\n",
p11_mechanism_to_name(oaep_params.hashAlg),
p11_mgf_to_name(oaep_params.mgf),
oaep_params.source,
oaep_params.pSourceData,
oaep_params.ulSourceDataLen);
}
rv = p11->C_DecryptInit(session, &mech, key);
if (rv != CKR_OK)
p11_fatal("C_DecryptInit", rv);
@ -5781,6 +5856,7 @@ static struct mech_info p11_mechanisms[] = {
{ CKM_MD2_RSA_PKCS, "MD2-RSA-PKCS", NULL },
{ CKM_MD5_RSA_PKCS, "MD5-RSA-PKCS", "rsa-md5" },
{ CKM_SHA1_RSA_PKCS, "SHA1-RSA-PKCS", "rsa-sha1" },
{ CKM_SHA224_RSA_PKCS, "SHA224-RSA-PKCS", "rsa-sha224" },
{ CKM_SHA256_RSA_PKCS, "SHA256-RSA-PKCS", "rsa-sha256" },
{ CKM_SHA384_RSA_PKCS, "SHA384-RSA-PKCS", "rsa-sha384" },
{ CKM_SHA512_RSA_PKCS, "SHA512-RSA-PKCS", "rsa-sha512" },
@ -5792,6 +5868,7 @@ static struct mech_info p11_mechanisms[] = {
{ CKM_SHA1_RSA_X9_31, "SHA1-RSA-X9-31", NULL },
{ CKM_RSA_PKCS_PSS, "RSA-PKCS-PSS", NULL },
{ CKM_SHA1_RSA_PKCS_PSS, "SHA1-RSA-PKCS-PSS", "rsa-pss-sha1" },
{ CKM_SHA224_RSA_PKCS_PSS,"SHA224-RSA-PKCS-PSS", "rsa-pss-sha224" },
{ CKM_SHA256_RSA_PKCS_PSS,"SHA256-RSA-PKCS-PSS", "rsa-pss-sha256" },
{ CKM_SHA384_RSA_PKCS_PSS,"SHA384-RSA-PKCS-PSS", "rsa-pss-sha384" },
{ CKM_SHA512_RSA_PKCS_PSS,"SHA512-RSA-PKCS-PSS", "rsa-pss-sha512" },
@ -5840,6 +5917,8 @@ static struct mech_info p11_mechanisms[] = {
{ CKM_SHA_1, "SHA-1", NULL },
{ CKM_SHA_1_HMAC, "SHA-1-HMAC", NULL },
{ CKM_SHA_1_HMAC_GENERAL, "SHA-1-HMAC-GENERAL", NULL },
{ CKM_SHA224, "SHA224", NULL },
{ CKM_SHA224_HMAC, "SHA224-HMAC", NULL },
{ CKM_SHA256, "SHA256", NULL },
{ CKM_SHA256_HMAC, "SHA256-HMAC", NULL },
{ CKM_SHA384, "SHA384", NULL },