Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pkcs11-tool): add support for RSA OAEP encryption #3175

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
223 changes: 88 additions & 135 deletions src/tools/pkcs11-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1385,9 +1385,11 @@ int main(int argc, char * argv[])
find_object_flags(session, mf_flags, &object,
opt_object_id_len ? opt_object_id : NULL,
opt_object_id_len, 0);
} else if (!find_object(session, CKO_SECRET_KEY, &object,
opt_object_id_len ? opt_object_id : NULL, opt_object_id_len, 0))
util_fatal("Secret key not found");
} else if (!find_object(session, CKO_PUBLIC_KEY, &object,
opt_object_id_len ? opt_object_id : NULL, opt_object_id_len, 0))
if (!find_object(session, CKO_SECRET_KEY, &object,
opt_object_id_len ? opt_object_id : NULL, opt_object_id_len, 0))
util_fatal("Public/Secret key not found");
}

if (do_verify) {
Expand Down Expand Up @@ -2546,6 +2548,72 @@ static void verify_signature(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
printf("Cryptoki returned error: %s\n", CKR2Str(rv));
}

static void
build_rsa_oaep_params(
CK_RSA_PKCS_OAEP_PARAMS *oaep_params,
CK_MECHANISM *mech,
char *param,
int param_len)
{
/* An RSA-OAEP mechanism needs parameters */

/* set "default" MGF and hash algorithms. We can overwrite MGF later */
oaep_params->hashAlg = opt_hash_alg;
switch (opt_hash_alg) {
case CKM_SHA_1:
oaep_params->mgf = CKG_MGF1_SHA1;
break;
case CKM_SHA224:
oaep_params->mgf = CKG_MGF1_SHA224;
break;
case CKM_SHA3_224:
oaep_params->mgf = CKG_MGF1_SHA3_224;
break;
case CKM_SHA3_256:
oaep_params->mgf = CKG_MGF1_SHA3_256;
break;
case CKM_SHA3_384:
oaep_params->mgf = CKG_MGF1_SHA3_384;
break;
case CKM_SHA3_512:
oaep_params->mgf = CKG_MGF1_SHA3_512;
break;
default:
printf("hash-algorithm %s unknown, defaulting to CKM_SHA256\n", p11_mechanism_to_name(opt_hash_alg));
oaep_params->hashAlg = CKM_SHA256;
/* fall through */
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;
}

if (opt_mgf != 0) {
oaep_params->mgf = opt_mgf;
} else {
printf("mgf not set, defaulting to %s\n", p11_mgf_to_name(oaep_params->mgf));
}

oaep_params->source = CKZ_DATA_SPECIFIED;
oaep_params->pSourceData = param;
oaep_params->ulSourceDataLen = param_len;

mech->pParameter = oaep_params;
mech->ulParameterLen = sizeof(*oaep_params);

printf("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);
}

static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE key)
{
Expand All @@ -2566,7 +2634,6 @@ 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 "
Expand All @@ -2576,39 +2643,7 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
/* 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_SHA_1:
oaep_params.mgf = CKG_MGF1_SHA1;
break;
case CKM_SHA224:
oaep_params.mgf = CKG_MGF1_SHA224;
break;
case CKM_SHA3_224:
oaep_params.mgf = CKG_MGF1_SHA3_224;
break;
case CKM_SHA3_256:
oaep_params.mgf = CKG_MGF1_SHA3_256;
break;
case CKM_SHA3_384:
oaep_params.mgf = CKG_MGF1_SHA3_384;
break;
case CKM_SHA3_512:
oaep_params.mgf = CKG_MGF1_SHA3_512;
break;
default:
oaep_params.hashAlg = CKM_SHA256;
/* fall through */
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;
}
build_rsa_oaep_params(&oaep_params, &mech, NULL, 0);
break;
case CKM_RSA_X_509:
case CKM_RSA_PKCS:
Expand All @@ -2627,29 +2662,6 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
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);

}

if (opt_input == NULL)
fd_in = 0;
else if ((fd_in = open(opt_input, O_RDONLY | O_BINARY)) < 0)
Expand Down Expand Up @@ -2720,6 +2732,7 @@ static void encrypt_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_in, fd_out;
ssize_t sz;
Expand All @@ -2734,7 +2747,14 @@ static void encrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
memset(&mech, 0, sizeof(mech));
mech.mechanism = opt_mechanism;

if (opt_hash_alg != 0 && opt_mechanism != CKM_RSA_PKCS_OAEP)
util_fatal("The hash-algorithm is applicable only to "
"RSA-PKCS-OAEP mechanism");

switch (opt_mechanism) {
case CKM_RSA_PKCS_OAEP:
Jakuje marked this conversation as resolved.
Show resolved Hide resolved
build_rsa_oaep_params(&oaep_params, &mech, NULL, 0);
break;
case CKM_AES_ECB:
mech.pParameter = NULL;
mech.ulParameterLen = 0;
Expand Down Expand Up @@ -7398,8 +7418,7 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session,
CK_ULONG encrypted_len, data_len;
int failed;
CK_RV rv;
int pad;
CK_MECHANISM_TYPE hash_alg = CKM_SHA256;
int pad;
CK_RSA_PKCS_MGF_TYPE mgf = CKG_MGF1_SHA256;
CK_RSA_PKCS_OAEP_PARAMS oaep_params;

Expand Down Expand Up @@ -7427,50 +7446,11 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session,
max_in_len = mod_len-11;
in_len = 10;
break;
case CKM_RSA_PKCS_OAEP: {
if (opt_hash_alg != 0) {
hash_alg = opt_hash_alg;
}
switch (hash_alg) {
case CKM_SHA_1:
mgf = CKG_MGF1_SHA1;
break;
case CKM_SHA224:
mgf = CKG_MGF1_SHA224;
break;
default:
printf("hash-algorithm %s unknown, defaulting to CKM_SHA256\n", p11_mechanism_to_name(hash_alg));
/* fall through */
case CKM_SHA256:
mgf = CKG_MGF1_SHA256;
break;
case CKM_SHA384:
mgf = CKG_MGF1_SHA384;
break;
case CKM_SHA512:
mgf = CKG_MGF1_SHA512;
break;
case CKM_SHA3_224:
mgf = CKG_MGF1_SHA3_224;
break;
case CKM_SHA3_256:
mgf = CKG_MGF1_SHA3_256;
break;
case CKM_SHA3_384:
mgf = CKG_MGF1_SHA3_384;
break;
case CKM_SHA3_512:
mgf = CKG_MGF1_SHA3_512;
break;
}
if (opt_mgf != 0) {
mgf = opt_mgf;
} else {
printf("mgf not set, defaulting to %s\n", p11_mgf_to_name(mgf));
}
case CKM_RSA_PKCS_OAEP:
build_rsa_oaep_params(&oaep_params, &mech, param, param_len);

pad = RSA_PKCS1_OAEP_PADDING;
size_t len = 2+2*hash_length(hash_alg);
size_t len = 2 + 2 * hash_length(oaep_params.hashAlg);
if (len >= mod_len) {
printf("Incompatible mechanism and key size\n");
return 0;
Expand All @@ -7479,7 +7459,6 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session,
max_in_len = mod_len-len;
in_len = 10;
break;
}
case CKM_RSA_X_509:
pad = RSA_NO_PADDING;
/* input length equals modulus length */
Expand Down Expand Up @@ -7526,15 +7505,15 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session,
if (mech_type == CKM_RSA_PKCS_OAEP) {
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
const EVP_MD *md;
switch (hash_alg) {
switch (oaep_params.hashAlg) {
case CKM_SHA_1:
md = EVP_sha1();
break;
case CKM_SHA224:
md = EVP_sha224();
break;
default: /* it should not happen, hash_alg is checked earlier */
/* fall through */
default: /* it should not happen, oaep_params.hashAlg is checked earlier */
/* fall through */
case CKM_SHA256:
md = EVP_sha256();
break;
Expand Down Expand Up @@ -7615,7 +7594,7 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session,
}
}
#else
if (hash_alg != CKM_SHA_1) {
if (oaep_params.hashAlg != CKM_SHA_1) {
printf("This version of OpenSSL only supports SHA1 for OAEP, returning\n");
return 0;
}
Expand All @@ -7633,34 +7612,8 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session,
EVP_PKEY_free(pkey);
encrypted_len = out_len;

/* set "default" MGF and hash algorithms. We can overwrite MGF later */
switch (mech_type) {
case CKM_RSA_PKCS_OAEP:
oaep_params.hashAlg = hash_alg;
oaep_params.mgf = mgf;

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 */

fprintf(stderr, "OAEP parameters: hashAlg=%s, mgf=%s, ",
p11_mechanism_to_name(oaep_params.hashAlg),
p11_mgf_to_name(oaep_params.mgf));

if (param != NULL && param_len > 0) {
oaep_params.source = CKZ_DATA_SPECIFIED;
oaep_params.pSourceData = param;
oaep_params.ulSourceDataLen = param_len;
fprintf(stderr, "encoding parameter (Label) present, length %d\n", param_len);
} else {
fprintf(stderr, "encoding parameter (Label) not present\n");
}

mech.pParameter = &oaep_params;
mech.ulParameterLen = sizeof(oaep_params);



break;
case CKM_RSA_X_509:
case CKM_RSA_PKCS:
Expand Down