You've already forked opencryptoki
mirror of
https://github.com/opencryptoki/opencryptoki.git
synced 2026-10-24 05:39:17 +03:00
Add check_unwrap_sensitive_extractable() to the common test code. It unwraps the same data with each combination of CKA_SENSITIVE and CKA_EXTRACTABLE, and with neither, and checks every new key: the attributes match the template (any value is accepted when the template does not set them, since the defaults are token specific); CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE are FALSE; and the key value cannot be read from a sensitive key. When the unwrapping key's CKA_UNWRAP_TEMPLATE sets one of the attributes, a key unwrapped without it gets that value, and a template asking for the other value must fail with CKR_TEMPLATE_INCONSISTENT. CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE are not checked on the ICSF token, which unwraps on the ICSF server and takes these attributes from it. Run it from do_WrapUnwrapAES() for secret keys, from do_WrapUnwrapRSA() for RSA private keys, and from both EC key transfer tests for EC private keys, whose transport key's CKA_UNWRAP_TEMPLATE sets CKA_EXTRACTABLE = FALSE. Add do_UnwrapTemplateAES(), which unwraps under a wrapping key whose CKA_UNWRAP_TEMPLATE sets CKA_SENSITIVE = TRUE and CKA_EXTRACTABLE = FALSE, for every AES wrap mechanism. Signed-off-by: Alexandre Laroche <larochealexandre@hotmail.com> Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
5766 lines
228 KiB
C
5766 lines
228 KiB
C
/*
|
|
* COPYRIGHT (c) International Business Machines Corp. 2011-2017
|
|
*
|
|
* This program is provided under the terms of the Common Public License,
|
|
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
* found in the file LICENSE file or at
|
|
* https://opensource.org/licenses/cpl1.0.php
|
|
*/
|
|
|
|
#include <windows.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
|
|
#include <openssl/hmac.h>
|
|
|
|
#include "pkcs11types.h"
|
|
#include "regress.h"
|
|
#include "common.c"
|
|
#include "ec.h"
|
|
#include "defs.h"
|
|
#include "ec_curves.h"
|
|
#include "mechtable.h"
|
|
#include "mech_to_str.h"
|
|
|
|
/*
|
|
* Below is a list for the OIDs and DER encodings of the brainpool.
|
|
* Beginning of each DER encoding should be 06 for OID and 09 for the length.
|
|
* For example brainpoolP160r1 should be 06092B2403030208010101
|
|
* brainpoolP160r1
|
|
* 1.3.36.3.3.2.8.1.1.1
|
|
* 2B2403030208010101
|
|
* brainpoolP160t1
|
|
* 1.3.36.3.3.2.8.1.1.2
|
|
* 2B2403030208010102
|
|
* brainpoolP192r1
|
|
* 1.3.36.3.3.2.8.1.1.3
|
|
* 2B2403030208010103
|
|
* brainpoolP192t1
|
|
* 1.3.36.3.3.2.8.1.1.4
|
|
* 2B2403030208010104
|
|
* brainpoolP224r1
|
|
* 1.3.36.3.3.2.8.1.1.5
|
|
* 2B2403030208010105
|
|
* brainpoolP224t1
|
|
* 1.3.36.3.3.2.8.1.1.6
|
|
* 2B2403030208010106
|
|
* brainpoolP256r1
|
|
* 1.3.36.3.3.2.8.1.1.7
|
|
* 2B2403030208010107
|
|
* brainpoolP256t1
|
|
* 1.3.36.3.3.2.8.1.1.8
|
|
* 2B2403030208010108
|
|
* brainpoolP320r1
|
|
* 1.3.36.3.3.2.8.1.1.9
|
|
* 2B2403030208010109
|
|
* brainpoolP320t1
|
|
* 1.3.36.3.3.2.8.1.1.10
|
|
* 2B240303020801010A
|
|
* brainpoolP384r1
|
|
* 1.3.36.3.3.2.8.1.1.11
|
|
* 2B240303020801010B
|
|
* brainpoolP384t1
|
|
* 1.3.36.3.3.2.8.1.1.12
|
|
* 2B240303020801010C
|
|
* brainpoolP512r1
|
|
* 1.3.36.3.3.2.8.1.1.13
|
|
* 2B240303020801010D
|
|
* brainpoolP512t1
|
|
* 1.3.36.3.3.2.8.1.1.14
|
|
* 2B240303020801010E
|
|
* prime192
|
|
* 1.2.840.10045.3.1.1
|
|
* 2A8648CE3D030101
|
|
* secp224
|
|
* 1.3.132.0.33
|
|
* 2B81040021
|
|
* prime256
|
|
* 1.2.840.10045.3.1.7
|
|
* 2A8648CE3D030107
|
|
* secp384
|
|
* 1.3.132.0.34
|
|
* 2B81040022
|
|
* secp521
|
|
* 1.3.132.0.35
|
|
* 2B81040023
|
|
* secp256k1
|
|
* 1.3.132.0.10
|
|
* 2B8104000A
|
|
* curve25519
|
|
* 1.3.101.110
|
|
* 06032B656E
|
|
* curve448[]
|
|
* 1.3.101.111
|
|
* 06032B656F
|
|
* ed25519[]
|
|
* 1.3.101.112
|
|
* 06032B6570
|
|
* ed448
|
|
* 1.3.101.113
|
|
* 06032B6571
|
|
*/
|
|
|
|
typedef struct ec_struct {
|
|
void const *curve;
|
|
CK_ULONG size;
|
|
CK_BBOOL twisted;
|
|
enum curve_type type;
|
|
CK_ULONG bit_len;
|
|
char *name;
|
|
} _ec_struct;
|
|
|
|
/* Supported Elliptic Curves */
|
|
#define NUMEC 25
|
|
const CK_BYTE brainpoolP160r1[] = OCK_BRAINPOOL_P160R1;
|
|
const CK_BYTE brainpoolP160t1[] = OCK_BRAINPOOL_P160T1;
|
|
const CK_BYTE brainpoolP192r1[] = OCK_BRAINPOOL_P192R1;
|
|
const CK_BYTE brainpoolP192t1[] = OCK_BRAINPOOL_P192T1;
|
|
const CK_BYTE brainpoolP224r1[] = OCK_BRAINPOOL_P224R1;
|
|
const CK_BYTE brainpoolP224t1[] = OCK_BRAINPOOL_P224T1;
|
|
const CK_BYTE brainpoolP256r1[] = OCK_BRAINPOOL_P256R1;
|
|
const CK_BYTE brainpoolP256t1[] = OCK_BRAINPOOL_P256T1;
|
|
const CK_BYTE brainpoolP320r1[] = OCK_BRAINPOOL_P320R1;
|
|
const CK_BYTE brainpoolP320t1[] = OCK_BRAINPOOL_P320T1;
|
|
const CK_BYTE brainpoolP384r1[] = OCK_BRAINPOOL_P384R1;
|
|
const CK_BYTE brainpoolP384t1[] = OCK_BRAINPOOL_P384T1;
|
|
const CK_BYTE brainpoolP512r1[] = OCK_BRAINPOOL_P512R1;
|
|
const CK_BYTE brainpoolP512t1[] = OCK_BRAINPOOL_P512T1;
|
|
const CK_BYTE prime192v1[] = OCK_PRIME192V1;
|
|
const CK_BYTE secp224r1[] = OCK_SECP224R1;
|
|
const CK_BYTE prime256v1[] = OCK_PRIME256V1;
|
|
const CK_BYTE secp384r1[] = OCK_SECP384R1;
|
|
const CK_BYTE secp521r1[] = OCK_SECP521R1;
|
|
const CK_BYTE secp256k1[] = OCK_SECP256K1;
|
|
const CK_BYTE curve25519[] = OCK_CURVE25519;
|
|
const CK_BYTE curve448[] = OCK_CURVE448;
|
|
const CK_BYTE ed25519[] = OCK_ED25519;
|
|
const CK_BYTE ed448[] = OCK_ED448;
|
|
const CK_BYTE bls12_381[] = OCK_BLS12_381;
|
|
|
|
const _ec_struct der_ec_supported[NUMEC] = {
|
|
{&brainpoolP160r1, sizeof(brainpoolP160r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE160_LENGTH, "brainpoolP160r1"},
|
|
{&brainpoolP160t1, sizeof(brainpoolP160t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
CURVE160_LENGTH, "brainpoolP160t1"},
|
|
{&brainpoolP192r1, sizeof(brainpoolP192r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE192_LENGTH, "brainpoolP192r1"},
|
|
{&brainpoolP192t1, sizeof(brainpoolP192t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
CURVE192_LENGTH, "brainpoolP192t1"},
|
|
{&brainpoolP224r1, sizeof(brainpoolP224r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE224_LENGTH, "brainpoolP224r1"},
|
|
{&brainpoolP224t1, sizeof(brainpoolP224t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
CURVE224_LENGTH, "brainpoolP224t1"},
|
|
{&brainpoolP256r1, sizeof(brainpoolP256r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE256_LENGTH, "brainpoolP256r1"},
|
|
{&brainpoolP256t1, sizeof(brainpoolP256t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
CURVE256_LENGTH, "brainpoolP256t1"},
|
|
{&brainpoolP320r1, sizeof(brainpoolP320r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE320_LENGTH, "brainpoolP320r1"},
|
|
{&brainpoolP320t1, sizeof(brainpoolP320t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
CURVE320_LENGTH, "brainpoolP320t1"},
|
|
{&brainpoolP384r1, sizeof(brainpoolP384r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE384_LENGTH, "brainpoolP384r1"},
|
|
{&brainpoolP384t1, sizeof(brainpoolP384t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
CURVE384_LENGTH, "brainpoolP384t1"},
|
|
{&brainpoolP512r1, sizeof(brainpoolP512r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE512_LENGTH, "brainpoolP512r1"},
|
|
{&brainpoolP512t1, sizeof(brainpoolP512t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
CURVE512_LENGTH, "brainpoolP512t1"},
|
|
{&prime192v1, sizeof(prime192v1), CK_FALSE, CURVE_PRIME,
|
|
CURVE192_LENGTH, "prime192v1"},
|
|
{&secp224r1, sizeof(secp224r1), CK_FALSE, CURVE_PRIME,
|
|
CURVE224_LENGTH , "secp224r1"},
|
|
{&prime256v1, sizeof(prime256v1), CK_FALSE, CURVE_PRIME,
|
|
CURVE256_LENGTH, "prime256v1"},
|
|
{&secp384r1, sizeof(secp384r1), CK_FALSE, CURVE_PRIME,
|
|
CURVE384_LENGTH, "secp384r1"},
|
|
{&secp521r1, sizeof(secp521r1), CK_FALSE, CURVE_PRIME,
|
|
CURVE521_LENGTH + 8, "secp521r1"},
|
|
{&secp256k1, sizeof(secp256k1), CK_FALSE, CURVE_KOBLITZ,
|
|
CURVE256_LENGTH, "secp256k1"},
|
|
{&curve25519, sizeof(curve25519), CK_FALSE, CURVE_MONTGOMERY,
|
|
CURVE256_LENGTH, "curve25519"},
|
|
{&curve448, sizeof(curve448), CK_FALSE, CURVE_MONTGOMERY,
|
|
CURVE448_LENGTH, "curve448"},
|
|
{&ed25519, sizeof(ed25519), CK_FALSE, CURVE_EDWARDS,
|
|
CURVE256_LENGTH, "ed25519"},
|
|
{&ed448, sizeof(ed448), CK_FALSE, CURVE_EDWARDS,
|
|
CURVE456_LENGTH, "ed448"},
|
|
{&bls12_381, sizeof(bls12_381), CK_TRUE, CURVE_BLS12_381,
|
|
CURVE384_LENGTH, "bls12_381"},
|
|
};
|
|
|
|
/* Invalid curves */
|
|
#define NUMECINVAL 4
|
|
const CK_BYTE invalidCurve[] =
|
|
{ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x08, 0x08, 0x01, 0x01, 0x01 };
|
|
const CK_BYTE invalidLen1[] =
|
|
{ 0x06, 0x0A, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01 };
|
|
const CK_BYTE invalidLen2[] =
|
|
{ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01 };
|
|
const CK_BYTE invalidOIDfield[] =
|
|
{ 0x05, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01 };
|
|
|
|
const _ec_struct der_ec_notsupported[NUMECINVAL] = {
|
|
{&invalidCurve, sizeof(invalidCurve), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE256_LENGTH, "invalidCurve"},
|
|
{&invalidLen1, sizeof(invalidLen1), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE256_LENGTH, "invalidLen1"},
|
|
{&invalidLen2, sizeof(invalidLen2), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE256_LENGTH, "invalidLen2"},
|
|
{&invalidOIDfield, sizeof(invalidOIDfield), CK_FALSE, CURVE_BRAINPOOL,
|
|
CURVE256_LENGTH, "invalidOIDfield"}
|
|
};
|
|
|
|
typedef struct signVerifyParam {
|
|
CK_MECHANISM mech;
|
|
CK_ULONG inputlen;
|
|
CK_ULONG parts; /* 0 means process in 1 chunk via C_Sign,
|
|
* >0 means process in n chunks via
|
|
* C_SignUpdate/C_SignFinal
|
|
*/
|
|
const char *name;
|
|
} _signVerifyParam;
|
|
|
|
CK_IBM_ECDSA_OTHER_PARAMS other_rand = { .submechanism = CKM_IBM_ECSDSA_RAND };
|
|
CK_IBM_ECDSA_OTHER_PARAMS other_compr_multi =
|
|
{ .submechanism = CKM_IBM_ECSDSA_COMPR_MULTI };
|
|
CK_IBM_ECDSA_OTHER_PARAMS other_bls =
|
|
{ .submechanism = CKM_IBM_BLS };
|
|
|
|
_signVerifyParam signVerifyInput[] = {
|
|
{{CKM_ECDSA, NULL, 0}, 20, 0, ""},
|
|
{{CKM_ECDSA, NULL, 0}, 32, 0, ""},
|
|
{{CKM_ECDSA, NULL, 0}, 48, 0, ""},
|
|
{{CKM_ECDSA, NULL, 0}, 64, 0, ""},
|
|
{{CKM_ECDSA_SHA1, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA1, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA1, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA1, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA224, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA224, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA224, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA224, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA256, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA256, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA256, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA256, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA384, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA384, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA384, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA384, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA512, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA512, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA512, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA512, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA3_224, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA3_224, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA3_224, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA3_224, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA3_256, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA3_256, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA3_256, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA3_256, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA3_384, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA3_384, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA3_384, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA3_384, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_ECDSA_SHA3_512, NULL, 0}, 100, 0, ""},
|
|
{{CKM_ECDSA_SHA3_512, NULL, 0}, 100, 4, ""},
|
|
{{CKM_ECDSA_SHA3_512, NULL, 0}, 0, 0, ""}, /* Empty Message via C_Sign */
|
|
{{CKM_ECDSA_SHA3_512, NULL, 0}, 0, 1, ""}, /* Empty Message via C_SignInit+C_SignFinal */
|
|
{{CKM_IBM_ED25519_SHA512, NULL, 0}, 100, 0, ""},
|
|
{{CKM_IBM_ED448_SHA3, NULL, 0}, 100, 0, ""},
|
|
{{CKM_IBM_ECDSA_OTHER, &other_rand, sizeof(other_rand)}, 20, 0, ""},
|
|
{{CKM_IBM_ECDSA_OTHER, &other_compr_multi, sizeof(other_compr_multi)}, 20, 0, ""},
|
|
{{CKM_IBM_ECDSA_OTHER, &other_bls, sizeof(other_bls)}, 20, 0, ""},
|
|
};
|
|
|
|
#define NUM_KDFS sizeof(kdfs)/sizeof(CK_EC_KDF_TYPE)
|
|
static CK_EC_KDF_TYPE kdfs[] = {
|
|
CKD_NULL,
|
|
CKD_SHA1_KDF,
|
|
CKD_SHA224_KDF,
|
|
CKD_SHA256_KDF,
|
|
CKD_SHA384_KDF,
|
|
CKD_SHA512_KDF,
|
|
CKD_SHA3_224_KDF,
|
|
CKD_SHA3_256_KDF,
|
|
CKD_SHA3_384_KDF,
|
|
CKD_SHA3_512_KDF,
|
|
CKD_SHA1_KDF_SP800,
|
|
CKD_SHA224_KDF_SP800,
|
|
CKD_SHA256_KDF_SP800,
|
|
CKD_SHA384_KDF_SP800,
|
|
CKD_SHA512_KDF_SP800,
|
|
CKD_SHA3_224_KDF_SP800,
|
|
CKD_SHA3_256_KDF_SP800,
|
|
CKD_SHA3_384_KDF_SP800,
|
|
CKD_SHA3_512_KDF_SP800,
|
|
};
|
|
|
|
static const char *p11_get_ckd(CK_EC_KDF_TYPE kdf)
|
|
{
|
|
switch (kdf) {
|
|
case CKD_NULL:
|
|
return "CKD_NULL";
|
|
case CKD_SHA1_KDF:
|
|
return "CKD_SHA1_KDF";
|
|
case CKD_SHA224_KDF:
|
|
return "CKD_SHA224_KDF";
|
|
case CKD_SHA256_KDF:
|
|
return "CKD_SHA256_KDF";
|
|
case CKD_SHA384_KDF:
|
|
return "CKD_SHA384_KDF";
|
|
case CKD_SHA512_KDF:
|
|
return "CKD_SHA512_KDF";
|
|
case CKD_SHA3_224_KDF:
|
|
return "CKD_SHA3_224_KDF";
|
|
case CKD_SHA3_256_KDF:
|
|
return "CKD_SHA3_256_KDF";
|
|
case CKD_SHA3_384_KDF:
|
|
return "CKD_SHA3_384_KDF";
|
|
case CKD_SHA3_512_KDF:
|
|
return "CKD_SHA3_512_KDF";
|
|
case CKD_SHA1_KDF_SP800:
|
|
return "CKD_SHA1_KDF_SP800";
|
|
case CKD_SHA224_KDF_SP800:
|
|
return "CKD_SHA224_KDF_SP800";
|
|
case CKD_SHA256_KDF_SP800:
|
|
return "CKD_SHA256_KDF_SP800";
|
|
case CKD_SHA384_KDF_SP800:
|
|
return "CKD_SHA384_KDF_SP800";
|
|
case CKD_SHA512_KDF_SP800:
|
|
return "CKD_SHA512_KDF_SP800";
|
|
case CKD_SHA3_224_KDF_SP800:
|
|
return "CKD_SHA3_224_KDF_SP800";
|
|
case CKD_SHA3_256_KDF_SP800:
|
|
return "CKD_SHA3_256_KDF_SP800";
|
|
case CKD_SHA3_384_KDF_SP800:
|
|
return "CKD_SHA3_384_KDF_SP800";
|
|
case CKD_SHA3_512_KDF_SP800:
|
|
return "CKD_SHA3_512_KDF_SP800";
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
static unsigned int curve_len(int index)
|
|
{
|
|
if (index >= NUMEC)
|
|
return 0;
|
|
|
|
return der_ec_supported[index].bit_len / 8;
|
|
}
|
|
|
|
static CK_RV curve_supported(const char *name)
|
|
{
|
|
if (name[strlen(name) - 2] == 'r' || name[strlen(name) - 2] == 'v' ||
|
|
name[strlen(name) - 2] == 'k')
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* A test is skipped, when no KDF is used and the derived key length
|
|
* shall be bigger than the shared secret (z-value). Without a KDF, max
|
|
* z-length key bytes can be derived.
|
|
*/
|
|
static unsigned int too_many_key_bytes_requested(unsigned int curve,
|
|
unsigned int kdf,
|
|
unsigned int keylen)
|
|
{
|
|
if (kdf > 0 || keylen <= curve_len(curve))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Perform a HMAC sign to verify that the key is usable.
|
|
*/
|
|
CK_RV run_HMACSign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE h_key,
|
|
CK_ULONG key_len, CK_MECHANISM_TYPE hmac_mech,
|
|
CK_BYTE *mac, CK_ULONG *mac_len)
|
|
{
|
|
CK_MECHANISM mech = { .mechanism = hmac_mech,
|
|
.pParameter = NULL, .ulParameterLen = 0 };
|
|
CK_BYTE data[32] = { 0 };
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (!mech_supported(SLOT_ID, mech.mechanism)) {
|
|
testcase_notice("Mechanism %s is not supported with slot "
|
|
"%lu. Skipping key check",
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism),
|
|
SLOT_ID);
|
|
*mac_len = 0;
|
|
return CKR_OK;
|
|
}
|
|
if (!check_supp_keysize(SLOT_ID, mech.mechanism, key_len * 8)) {
|
|
testcase_notice("Mechanism %s can not be used with keys "
|
|
"of size %lu. Skipping key check",
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism),
|
|
key_len);
|
|
*mac_len = 0;
|
|
return CKR_OK;
|
|
}
|
|
|
|
rc = funcs->C_SignInit(session, &mech, h_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_notice("C_SignInit rc=%s", p11_get_ckr(rc));
|
|
goto error;
|
|
}
|
|
|
|
/** do signing **/
|
|
rc = funcs->C_Sign(session, data, sizeof(data), mac, mac_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_notice("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
return rc;
|
|
}
|
|
|
|
CK_RV run_AESEncrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE h_key,
|
|
CK_BYTE *enc, CK_ULONG *enc_len)
|
|
{
|
|
char aes_iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
|
};
|
|
CK_MECHANISM mech = { .mechanism = CKM_AES_CBC,
|
|
.pParameter = &aes_iv,
|
|
.ulParameterLen = AES_INIT_VECTOR_SIZE };
|
|
CK_BYTE data[AES_BLOCK_SIZE] = { 0 };
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (!mech_supported(SLOT_ID, mech.mechanism)) {
|
|
testcase_notice("Mechanism %s is not supported with slot "
|
|
"%lu. Skipping key check",
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism),
|
|
SLOT_ID);
|
|
*enc_len = 0;
|
|
return CKR_OK;
|
|
}
|
|
|
|
rc = funcs->C_EncryptInit(session, &mech, h_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_notice("C_EncryptInit rc=%s", p11_get_ckr(rc));
|
|
goto error;
|
|
}
|
|
|
|
/** do encrypting **/
|
|
rc = funcs->C_Encrypt(session, data, sizeof(data), enc, enc_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_notice("C_Encrypt rc=%s", p11_get_ckr(rc));
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Perform a HMAC sign to verify that the key is usable.
|
|
*/
|
|
CK_RV run_HMACSign_OpenSSL(CK_BYTE *key, CK_ULONG key_len,
|
|
CK_MECHANISM_TYPE hmac_mech,
|
|
CK_BYTE *mac, CK_ULONG *mac_len)
|
|
{
|
|
CK_BYTE data[32] = { 0 };
|
|
const EVP_MD *md;
|
|
unsigned int out_len;
|
|
|
|
switch (hmac_mech) {
|
|
case CKM_SHA_1_HMAC:
|
|
md = EVP_sha1();
|
|
break;
|
|
case CKM_SHA224_HMAC:
|
|
md = EVP_sha224();
|
|
break;
|
|
case CKM_SHA256_HMAC:
|
|
md = EVP_sha256();
|
|
break;
|
|
case CKM_SHA384_HMAC:
|
|
md = EVP_sha384();
|
|
break;
|
|
case CKM_SHA512_HMAC:
|
|
md = EVP_sha512();
|
|
break;
|
|
default:
|
|
testcase_notice("Mechanism %s is not supported. Skipping key check",
|
|
p11_get_ckm(&mechtable_funcs, hmac_mech));
|
|
*mac_len = 0;
|
|
return CKR_OK;
|
|
}
|
|
|
|
out_len = *mac_len;
|
|
if (HMAC(md, key, key_len, data, sizeof(data), mac, &out_len) == NULL) {
|
|
testcase_notice("HMAC (OpenSSL) failed");
|
|
return CKR_OK;
|
|
}
|
|
*mac_len = out_len;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/*
|
|
* Generate EC key-pairs for parties A and B.
|
|
* Derive shared secrets based on Diffie Hellman key agreement defined in PKCS#3
|
|
*/
|
|
CK_RV run_DeriveECDHKey(CK_BBOOL cofactor_mode)
|
|
{
|
|
CK_SESSION_HANDLE session;
|
|
CK_MECHANISM mech;
|
|
CK_FLAGS flags;
|
|
CK_OBJECT_HANDLE publ_keyA = CK_INVALID_HANDLE,
|
|
priv_keyA = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE publ_keyB = CK_INVALID_HANDLE,
|
|
priv_keyB = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE secret_keyA = CK_INVALID_HANDLE,
|
|
secret_keyB = CK_INVALID_HANDLE;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len;
|
|
CK_RV rc = CKR_OK;
|
|
CK_ECDH1_DERIVE_PARAMS ecdh_parmA, ecdh_parmB;
|
|
CK_BBOOL true = CK_TRUE;
|
|
CK_BBOOL false = CK_FALSE;
|
|
CK_BYTE pubkeyA_value[256] = { 0 };
|
|
CK_BYTE pubkeyB_value[256] = { 0 };
|
|
CK_BYTE secretA_value[80000] = { 0 }; //enough space for lengths in secret_key_len[]
|
|
CK_BYTE deriveB_value[80000] = { 0 };
|
|
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
|
|
CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
|
|
CK_ULONG i, j, k, m;
|
|
CK_MECHANISM_TYPE derive_mech_type;
|
|
|
|
testcase_begin("starting run_DeriveECDHKey with pkey=%X ...", pkey);
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (!mech_supported(SLOT_ID, CKM_EC_KEY_PAIR_GEN)) {
|
|
testcase_skip("Slot %u doesn't support CKM_EC_KEY_PAIR_GEN\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (i=0; i<NUMEC; i++) {
|
|
CK_ATTRIBUTE cka_derive_tmpl[] = {
|
|
{CKA_PRIVATE, &true, sizeof(true)},
|
|
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG derive_key_type = CKK_AES;
|
|
CK_ULONG derive_value_len = 256 / 8;
|
|
CK_ATTRIBUTE cka_derive_tmpl_cca[] = {
|
|
{CKA_PRIVATE, &true, sizeof(true)},
|
|
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
{CKA_KEY_TYPE, &derive_key_type, sizeof(derive_key_type)},
|
|
{CKA_VALUE_LEN, &derive_value_len, sizeof(derive_value_len)},
|
|
};
|
|
CK_ATTRIBUTE prv_attr[] = {
|
|
{CKA_SIGN, &true, sizeof(true)},
|
|
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
{CKA_DERIVE, &true, sizeof(true)},
|
|
{CKA_DERIVE_TEMPLATE, &cka_derive_tmpl, sizeof(cka_derive_tmpl)},
|
|
};
|
|
CK_ULONG prv_attr_len = sizeof(prv_attr)/sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE prv_attr_edwards[] = {
|
|
{CKA_SIGN, &true, sizeof(true)},
|
|
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG prv_attr_edwards_len =
|
|
sizeof(prv_attr_edwards)/sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE prv_attr_montgomery[] = {
|
|
{CKA_DERIVE, &true, sizeof(true)},
|
|
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
{CKA_DERIVE_TEMPLATE, &cka_derive_tmpl, sizeof(cka_derive_tmpl)},
|
|
};
|
|
CK_ULONG prv_attr_montgomery_len =
|
|
sizeof(prv_attr_montgomery)/sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_ATTRIBUTE pub_attr[] = {
|
|
{CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_supported[i].curve,
|
|
der_ec_supported[i].size},
|
|
{CKA_VERIFY, &true, sizeof(true)},
|
|
{CKA_MODIFIABLE, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG pub_attr_len = sizeof(pub_attr)/sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE pub_attr_montgomery[] = {
|
|
{CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_supported[i].curve,
|
|
der_ec_supported[i].size},
|
|
{CKA_MODIFIABLE, &true, sizeof(true)},
|
|
{CKA_VERIFY, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG pub_attr_montgomery_len =
|
|
sizeof(pub_attr_montgomery)/sizeof(CK_ATTRIBUTE);
|
|
|
|
if (is_icsf_token(SLOT_ID))
|
|
prv_attr_len -= 1; /* ICSF does not support array attributes */
|
|
if (is_cca_token(SLOT_ID)) {
|
|
prv_attr[3].pValue = cka_derive_tmpl_cca;
|
|
prv_attr[3].ulValueLen = sizeof(cka_derive_tmpl_cca);
|
|
}
|
|
|
|
CK_ATTRIBUTE *prv_attr_gen = prv_attr;
|
|
CK_ULONG prv_attr_gen_len = prv_attr_len;
|
|
CK_ATTRIBUTE *pub_attr_gen = pub_attr;
|
|
CK_ULONG pub_attr_gen_len = pub_attr_len;
|
|
|
|
CK_ATTRIBUTE extr1_tmpl[] = {
|
|
{CKA_EC_POINT, pubkeyA_value, sizeof(pubkeyA_value)},
|
|
};
|
|
CK_ULONG extr1_tmpl_len = sizeof(extr1_tmpl)/sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_ATTRIBUTE extr2_tmpl[] = {
|
|
{CKA_EC_POINT, pubkeyB_value, sizeof(pubkeyB_value)},
|
|
};
|
|
CK_ULONG extr2_tmpl_len = sizeof(extr2_tmpl)/sizeof(CK_ATTRIBUTE);
|
|
|
|
if (der_ec_supported[i].type == CURVE_EDWARDS||
|
|
der_ec_supported[i].type == CURVE_BLS12_381) {
|
|
/* Edwards/BLS curves can not be used for ECDH derive */
|
|
continue;
|
|
}
|
|
|
|
if (is_cca_token(SLOT_ID) || is_icsf_token(SLOT_ID)) {
|
|
if (der_ec_supported[i].twisted) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
if (der_ec_supported[i].type != CURVE_BRAINPOOL &&
|
|
der_ec_supported[i].type != CURVE_PRIME &&
|
|
der_ec_supported[i].type != CURVE_KOBLITZ) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
derive_mech_type = cofactor_mode ?
|
|
CKM_ECDH1_COFACTOR_DERIVE : CKM_ECDH1_DERIVE;
|
|
if (der_ec_supported[i].type == CURVE_MONTGOMERY) {
|
|
if (cofactor_mode) {
|
|
testcase_skip("No cofactor mode possible for curve: %s",
|
|
der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
if (der_ec_supported[i].curve == curve25519)
|
|
derive_mech_type = CKM_IBM_EC_X25519;
|
|
if (der_ec_supported[i].curve == curve448)
|
|
derive_mech_type = CKM_IBM_EC_X448;
|
|
|
|
prv_attr_gen = prv_attr_montgomery;
|
|
prv_attr_gen_len = prv_attr_montgomery_len;
|
|
pub_attr_gen = pub_attr_montgomery;
|
|
pub_attr_gen_len = pub_attr_montgomery_len;
|
|
} else if (der_ec_supported[i].type == CURVE_EDWARDS) {
|
|
if (cofactor_mode) {
|
|
testcase_skip("No cofactor mode possible for curve: %s",
|
|
der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
prv_attr_gen = prv_attr_edwards;
|
|
prv_attr_gen_len = prv_attr_edwards_len;
|
|
}
|
|
if (!mech_supported(SLOT_ID, derive_mech_type)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckm(&mechtable_funcs, derive_mech_type));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Testcase #1 - Generate 2 EC key pairs.
|
|
|
|
// First, generate the EC key pair for party A
|
|
mech.mechanism = CKM_EC_KEY_PAIR_GEN;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
rc = funcs->C_GenerateKeyPair(session, &mech,
|
|
pub_attr_gen, pub_attr_gen_len,
|
|
prv_attr_gen, prv_attr_gen_len,
|
|
&publ_keyA, &priv_keyA);
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
testcase_fail("C_GenerateKeyPair with valid input failed at i=%lu "
|
|
"(%s), rc=%s", i, der_ec_supported[i].name,
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Extract public key A
|
|
rc = funcs->C_GetAttributeValue(session, publ_keyA,
|
|
extr1_tmpl, extr1_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #1: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Now generate the EC key pair for party B
|
|
mech.mechanism = CKM_EC_KEY_PAIR_GEN;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
rc = funcs->C_GenerateKeyPair(session, &mech,
|
|
pub_attr_gen, pub_attr_gen_len,
|
|
prv_attr_gen, prv_attr_gen_len,
|
|
&publ_keyB, &priv_keyB);
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_fail("C_GenerateKeyPair with valid input failed at i=%lu "
|
|
"(%s), rc=%s", i, der_ec_supported[i].name,
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Extract public key B
|
|
rc = funcs->C_GetAttributeValue(session, publ_keyB,
|
|
extr2_tmpl, extr2_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #1: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Check if the key lengths are equal
|
|
if (extr1_tmpl->ulValueLen != extr2_tmpl->ulValueLen) {
|
|
testcase_error("Length of public key A not equal to length of "
|
|
"public key B");
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Testcase #2 - Now derive the secrets...
|
|
|
|
for (j=0; j < NUM_KDFS; j++) {
|
|
switch (kdfs[j]) {
|
|
case CKD_SHA1_KDF:
|
|
case CKD_SHA1_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA_1)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA224_KDF:
|
|
case CKD_SHA224_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA224)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA256_KDF:
|
|
case CKD_SHA256_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA256)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA384_KDF:
|
|
case CKD_SHA384_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA384)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA512_KDF:
|
|
case CKD_SHA512_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA512)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_224_KDF:
|
|
case CKD_SHA3_224_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_224)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));;
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_256_KDF:
|
|
case CKD_SHA3_256_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_256)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_384_KDF:
|
|
case CKD_SHA3_384_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_384)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_512_KDF:
|
|
case CKD_SHA3_512_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_512)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (is_icsf_token(SLOT_ID)) {
|
|
switch (kdfs[j]) {
|
|
case CKD_SHA1_KDF:
|
|
case CKD_SHA224_KDF:
|
|
case CKD_SHA256_KDF:
|
|
case CKD_SHA384_KDF:
|
|
break;
|
|
default:
|
|
testcase_skip("The ICSF token in slot %u doesn't support "
|
|
"%s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
for (k=0; k<NUM_SECRET_KEY_LENGTHS; k++) {
|
|
|
|
if (too_many_key_bytes_requested(i, j, secret_key_len[k])) {
|
|
/*
|
|
* Cannot provide requested key bytes with current curve
|
|
* without a kdf.
|
|
*/
|
|
continue;
|
|
}
|
|
if (is_ep11_token(SLOT_ID) && k > 9) {
|
|
testcase_skip("EP11 cannot provide %lu key bytes with "
|
|
"curve %s\n", secret_key_len[k],
|
|
der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
secret_key_len[k] > 0 && secret_key_len[k] < 10) {
|
|
/*
|
|
* EP11 can not derive keys less than 80 bits (10 bytes).
|
|
* This was formerly dependent on control point
|
|
* XCP_CPB_KEYSZ_BELOW80BIT, but this control point
|
|
* is now always OFF.
|
|
* */
|
|
testcase_skip("EP11 cannot provide %lu key bytes (%lu bits < 80 bits)\n",
|
|
secret_key_len[k], secret_key_len[k] * 8);
|
|
continue;
|
|
}
|
|
if (secret_key_len[k] == 0 &&
|
|
der_ec_supported[i].type == CURVE_MONTGOMERY) {
|
|
/*
|
|
* Curve can not be used without the derived key size
|
|
* specified in CKA_VALUE_LEN.
|
|
*/
|
|
continue;
|
|
}
|
|
if (der_ec_supported[i].type == CURVE_BLS12_381) {
|
|
/*
|
|
* Skipping BLS 12 381 curve.
|
|
*/
|
|
continue;
|
|
}
|
|
|
|
if (is_icsf_token(SLOT_ID) && secret_key_len[k] == 0) {
|
|
testcase_skip("ICSF token can not derive keys without CKA_VALUE_LEN\n");
|
|
continue;
|
|
}
|
|
if (is_icsf_token(SLOT_ID) && secret_key_len[k] > 256) {
|
|
testcase_skip("ICSF token can not derive keys of that size\n");
|
|
continue;
|
|
}
|
|
|
|
if (is_cca_token(SLOT_ID)) {
|
|
if (secret_key_len[k] == derive_value_len) {
|
|
key_type = derive_key_type; /* CCA can only derive AES-256 keys */
|
|
} else if (secret_key_len[k] == 0 &&
|
|
der_ec_supported[i].bit_len == derive_value_len * 8) {
|
|
key_type = derive_key_type; /* CCA can only derive AES-256 keys */
|
|
} else {
|
|
testcase_skip("CCA token can not derive keys of size %lu\n",
|
|
secret_key_len[k]);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
CK_ATTRIBUTE secretA_tmpl[] = {
|
|
{CKA_VALUE, secretA_value, sizeof(secretA_value)},
|
|
};
|
|
CK_ULONG secretA_tmpl_len =
|
|
sizeof(secretA_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_ATTRIBUTE secretB_tmpl[] = {
|
|
{CKA_VALUE, deriveB_value, sizeof(deriveB_value)},
|
|
};
|
|
CK_ULONG secretB_tmpl_len =
|
|
sizeof(secretB_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_ATTRIBUTE derive_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_SENSITIVE, &false, sizeof(false)},
|
|
{CKA_VALUE_LEN, &(secret_key_len[k]), sizeof(CK_ULONG)},
|
|
};
|
|
CK_ULONG secret_tmpl_len =
|
|
sizeof(derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_BYTE mac1[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac1_len = sizeof(mac1);
|
|
CK_BYTE mac2[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac2_len = sizeof(mac2);
|
|
CK_BYTE enc1[AES_BLOCK_SIZE] = { 0 };
|
|
CK_ULONG enc1_len = sizeof(enc1);
|
|
CK_BYTE enc2[AES_BLOCK_SIZE] = { 0 };
|
|
CK_ULONG enc2_len = sizeof(enc2);
|
|
|
|
if (secret_key_len[k] == 0)
|
|
secret_tmpl_len--;
|
|
|
|
for (m=0; m < (kdfs[j] == CKD_NULL ? 1 : NUM_SHARED_DATA); m++) {
|
|
|
|
if (is_cca_token(SLOT_ID)) {
|
|
switch (kdfs[j]) {
|
|
case CKD_SHA224_KDF:
|
|
case CKD_SHA256_KDF:
|
|
case CKD_SHA384_KDF:
|
|
case CKD_SHA512_KDF:
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
|
|
testcase_begin("Starting with curve=%s, kdf=%s, keylen=%lu, "
|
|
"shared_data=%u, mech=%s, pkey=%X",
|
|
der_ec_supported[i].name,
|
|
p11_get_ckd(kdfs[j]), secret_key_len[k],
|
|
shared_data[m].length,
|
|
p11_get_ckm(&mechtable_funcs, derive_mech_type),
|
|
pkey);
|
|
|
|
// Now, derive a generic secret key using party A's private
|
|
// key and B's public key
|
|
ecdh_parmA.kdf = kdfs[j];
|
|
ecdh_parmA.pPublicData = extr2_tmpl->pValue;
|
|
ecdh_parmA.ulPublicDataLen = extr2_tmpl->ulValueLen;
|
|
ecdh_parmA.pSharedData =
|
|
shared_data[m].length == 0 ?
|
|
NULL : (CK_BYTE_PTR) &shared_data[m].data;
|
|
ecdh_parmA.ulSharedDataLen = shared_data[m].length;
|
|
|
|
if (kdfs[j] == CKD_NULL) {
|
|
ecdh_parmA.pSharedData = NULL;
|
|
ecdh_parmA.ulSharedDataLen = 0;
|
|
}
|
|
|
|
mech.mechanism = derive_mech_type;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parmA;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
priv_keyA, derive_tmpl,
|
|
secret_tmpl_len, &secret_keyA);
|
|
if (rc != CKR_OK) {
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
(kdfs[j] != CKD_NULL ||
|
|
shared_data[m].length > 0)) {
|
|
testcase_skip("EP11 does not support KDF %s and/or "
|
|
"shared data with older firmware "
|
|
"versions\n",
|
|
p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
if (is_icsf_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
kdfs[j] != CKD_NULL &&
|
|
kdfs[j] != CKD_SHA224_KDF &&
|
|
kdfs[j] != CKD_SHA256_KDF &&
|
|
kdfs[j] != CKD_SHA384_KDF &&
|
|
kdfs[j] != CKD_SHA512_KDF) {
|
|
testcase_skip("ICSF does not support KDF %s\n",
|
|
p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("key derivation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_FUNCTION_CANCELED) {
|
|
testcase_skip("key derivation is not allowed by "
|
|
"adapter control point");
|
|
continue;
|
|
}
|
|
if (rc == CKR_KEY_SIZE_RANGE) {
|
|
testcase_skip("key derivation is not allowed "
|
|
"because key to be generated is "
|
|
"stronger than the input material.");
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_DeriveKey #1: rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
switch (key_type) {
|
|
case CKK_GENERIC_SECRET:
|
|
mac1_len = sizeof(mac1);
|
|
rc = run_HMACSign(session, secret_keyA,
|
|
secret_key_len[k] > 0 ?
|
|
secret_key_len[k] : curve_len(i),
|
|
CKM_SHA_1_HMAC, mac1, &mac1_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Derived key #1 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
break;
|
|
|
|
case CKK_AES:
|
|
enc1_len = sizeof(enc1);
|
|
rc = run_AESEncrypt(session, secret_keyA,
|
|
enc1, &enc1_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Derived key #1 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Now, derive a generic secret key using B's private key
|
|
// and A's public key
|
|
ecdh_parmB.kdf = kdfs[j];
|
|
ecdh_parmB.pPublicData = extr1_tmpl->pValue;
|
|
ecdh_parmB.ulPublicDataLen = extr1_tmpl->ulValueLen;
|
|
ecdh_parmB.pSharedData =
|
|
shared_data[m].length == 0 ?
|
|
NULL : (CK_BYTE_PTR)&shared_data[m].data;
|
|
ecdh_parmB.ulSharedDataLen = shared_data[m].length;
|
|
|
|
if (kdfs[j] == CKD_NULL) {
|
|
ecdh_parmB.pSharedData = NULL;
|
|
ecdh_parmB.ulSharedDataLen = 0;
|
|
}
|
|
|
|
mech.mechanism = derive_mech_type;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parmB;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
priv_keyB, derive_tmpl,
|
|
secret_tmpl_len, &secret_keyB);
|
|
if (rc != CKR_OK) {
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
(kdfs[j] != CKD_NULL ||
|
|
shared_data[m].length > 0)) {
|
|
testcase_skip("EP11 does not support KDF %s and/or "
|
|
"shared data with older firmware "
|
|
"versions\n",
|
|
p11_get_ckd(kdfs[j]));
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
continue;
|
|
}
|
|
if (is_icsf_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
kdfs[j] != CKD_NULL &&
|
|
kdfs[j] != CKD_SHA224_KDF &&
|
|
kdfs[j] != CKD_SHA256_KDF &&
|
|
kdfs[j] != CKD_SHA384_KDF &&
|
|
kdfs[j] != CKD_SHA512_KDF) {
|
|
testcase_skip("ICSF does not support KDF %s\n",
|
|
p11_get_ckd(kdfs[j]));
|
|
continue;
|
|
}
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("key derivation is not allowed by policy");
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
continue;
|
|
}
|
|
if (rc == CKR_FUNCTION_CANCELED) {
|
|
testcase_skip("key derivation is not allowed by "
|
|
"adapter control point");
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
continue;
|
|
}
|
|
if (rc == CKR_KEY_SIZE_RANGE) {
|
|
testcase_skip("key derivation is not allowed "
|
|
"because key to be generated is "
|
|
"stronger than the input material.");
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_DeriveKey #2: rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
|
|
switch (key_type) {
|
|
case CKK_GENERIC_SECRET:
|
|
mac2_len = sizeof(mac2);
|
|
rc = run_HMACSign(session, secret_keyB,
|
|
secret_key_len[k] > 0 ?
|
|
secret_key_len[k] : curve_len(i),
|
|
CKM_SHA_1_HMAC, mac2, &mac2_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Derived key #2 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (mac1_len != mac2_len ||
|
|
memcmp(mac1, mac2, mac1_len) != 0) {
|
|
testcase_fail("ERROR: derived keys do not produce the "
|
|
"same HMAC");
|
|
goto testcase_cleanup;
|
|
}
|
|
break;
|
|
|
|
case CKK_AES:
|
|
enc2_len = sizeof(enc2);
|
|
rc = run_AESEncrypt(session, secret_keyA,
|
|
enc2, &enc2_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Derived key #1 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (enc1_len != enc2_len ||
|
|
memcmp(enc1, enc2, enc1_len) != 0) {
|
|
testcase_fail("ERROR: derived keys do not produce the "
|
|
"same encrypted cipher text");
|
|
goto testcase_cleanup;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* A secure key token won't reveal the key value in clear */
|
|
if (!is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
// Extract the derived secret A
|
|
rc = funcs->C_GetAttributeValue(session, secret_keyA,
|
|
secretA_tmpl,
|
|
secretA_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #3:rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Extract the derived secret B
|
|
rc = funcs->C_GetAttributeValue(session, secret_keyB,
|
|
secretB_tmpl,
|
|
secretB_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #4:rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Compare lengths of derived secrets from key object
|
|
if (secretA_tmpl[0].ulValueLen !=
|
|
secretB_tmpl[0].ulValueLen) {
|
|
testcase_fail("ERROR: derived key #1 length = %lu, "
|
|
"derived key #2 length = %lu",
|
|
secretA_tmpl[0].ulValueLen,
|
|
secretB_tmpl[0].ulValueLen);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// Compare derive secrets A and B
|
|
if (memcmp(secretA_tmpl[0].pValue,
|
|
secretB_tmpl[0].pValue,
|
|
secretA_tmpl[0].ulValueLen) != 0) {
|
|
testcase_fail("ERROR: derived key mismatch, curve=%s, "
|
|
"kdf=%s, keylen=%lu, shared_data=%u",
|
|
der_ec_supported[i].name,
|
|
p11_get_ckd(kdfs[j]), secret_key_len[k],
|
|
shared_data[m].length);
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
testcase_pass("*Derive shared secret curve=%s, kdf=%s, "
|
|
"keylen=%lu, shared_data=%u, mech=%s passed.",
|
|
der_ec_supported[i].name,
|
|
p11_get_ckd(kdfs[j]), secret_key_len[k],
|
|
shared_data[m].length,
|
|
p11_get_ckm(&mechtable_funcs, derive_mech_type));
|
|
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
} /* end run_DeriveECDHKey() */
|
|
|
|
/*
|
|
* Run some ECDH known answer tests.
|
|
*/
|
|
CK_RV run_DeriveECDHKeyKAT(void)
|
|
{
|
|
CK_SESSION_HANDLE session;
|
|
CK_MECHANISM mech;
|
|
CK_FLAGS flags;
|
|
CK_OBJECT_HANDLE publ_keyA = CK_INVALID_HANDLE,
|
|
priv_keyA = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE publ_keyB = CK_INVALID_HANDLE,
|
|
priv_keyB = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE secret_keyA = CK_INVALID_HANDLE,
|
|
secret_keyB = CK_INVALID_HANDLE;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_KEY_TYPE secret_key_type = CKK_GENERIC_SECRET;
|
|
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
|
|
CK_ECDH1_DERIVE_PARAMS ecdh_parmA, ecdh_parmB;
|
|
CK_BBOOL false = CK_FALSE;
|
|
CK_ULONG user_pin_len;
|
|
CK_RV rc = CKR_OK;
|
|
CK_BYTE secretA_value[1000] = { 0 }; // enough space for key lengths in ecdh_tv[]
|
|
CK_BYTE secretB_value[1000] = { 0 };
|
|
CK_BYTE mac1[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac1_len = sizeof(mac1);
|
|
CK_BYTE mac2[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac2_len = sizeof(mac2);
|
|
CK_BYTE macexpected[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG macexpected_len = sizeof(macexpected);
|
|
CK_ULONG i;
|
|
|
|
testcase_begin("starting run_DeriveECDHKeyKAT with pkey=%X ...", pkey);
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (!mech_supported(SLOT_ID, CKM_ECDH1_DERIVE)) {
|
|
testcase_skip("Slot %u doesn't support CKM_ECDH1_DERIVE\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if ((is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) &&
|
|
!mech_supported(SLOT_ID, CKM_SHA_1_HMAC)) {
|
|
testcase_skip("Slot %u doesn't support CKM_SHA_1_HMAC, correctness "
|
|
"of derived keys can not be verified\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (is_cca_token(SLOT_ID)) {
|
|
testcase_skip("The CCA token in slot %u doesn't support ECDH with EC "
|
|
"keys imported from clear, only with randomly generated "
|
|
"keys. KATs not possible because of that\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
|
|
for (i=0; i<ECDH_TV_NUM; i++) {
|
|
|
|
testcase_begin("Starting with shared secret i=%lu, pkey=%X", i, pkey);
|
|
|
|
switch (ecdh_tv[i].kdf) {
|
|
case CKD_SHA1_KDF:
|
|
case CKD_SHA1_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA_1)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA224_KDF:
|
|
case CKD_SHA224_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA224)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA256_KDF:
|
|
case CKD_SHA256_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA256)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA384_KDF:
|
|
case CKD_SHA384_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA384)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA512_KDF:
|
|
case CKD_SHA512_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA512)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_224_KDF:
|
|
case CKD_SHA3_224_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_224)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_256_KDF:
|
|
case CKD_SHA3_256_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_256)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_384_KDF:
|
|
case CKD_SHA3_384_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_384)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_512_KDF:
|
|
case CKD_SHA3_512_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_512)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (is_icsf_token(SLOT_ID)) {
|
|
switch (ecdh_tv[i].kdf) {
|
|
case CKD_SHA1_KDF:
|
|
case CKD_SHA224_KDF:
|
|
case CKD_SHA256_KDF:
|
|
case CKD_SHA384_KDF:
|
|
break;
|
|
default:
|
|
testcase_skip("The ICSF token in slot %u doesn't support "
|
|
"%s\n",
|
|
(unsigned int) SLOT_ID, p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (is_ep11_token(SLOT_ID) && ecdh_tv[i].derived_key_len > 256) {
|
|
testcase_skip("EP11 cannot provide %lu key bytes with "
|
|
"curve %s\n", ecdh_tv[i].derived_key_len,
|
|
ecdh_tv[i].name);
|
|
continue;
|
|
}
|
|
|
|
if ((is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) &&
|
|
!check_supp_keysize(SLOT_ID, CKM_SHA_1_HMAC,
|
|
ecdh_tv[i].derived_key_len * 8)) {
|
|
testcase_skip("Mechanism CKM_SHA_1_HMAC can not be used with "
|
|
"keys of size %lu. Correctness of derived key "
|
|
"can not be verified.",
|
|
ecdh_tv[i].derived_key_len);
|
|
continue;
|
|
}
|
|
|
|
if (is_icsf_token(SLOT_ID)) {
|
|
if (der_ec_supported[i].twisted) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
if (der_ec_supported[i].type != CURVE_BRAINPOOL &&
|
|
der_ec_supported[i].type != CURVE_PRIME &&
|
|
der_ec_supported[i].type != CURVE_KOBLITZ) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// First, import the EC key pair for party A
|
|
rc = create_ECPrivateKey(session, CKK_EC,
|
|
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
ecdh_tv[i].privkeyA, ecdh_tv[i].privkey_len,
|
|
&priv_keyA, !pkey, CK_TRUE);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = create_ECPublicKey(session, CKK_EC,
|
|
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
ecdh_tv[i].pubkeyA, ecdh_tv[i].pubkey_len,
|
|
&publ_keyA, !pkey);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Now import the EC key pair for party B
|
|
rc = create_ECPrivateKey(session, CKK_EC,
|
|
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
ecdh_tv[i].privkeyB, ecdh_tv[i].privkey_len,
|
|
&priv_keyB, !pkey, CK_TRUE);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = create_ECPublicKey(session, CKK_EC,
|
|
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
ecdh_tv[i].pubkeyB, ecdh_tv[i].pubkey_len,
|
|
&publ_keyB, !pkey);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Now derive the secrets...
|
|
|
|
CK_ATTRIBUTE secretA_tmpl[] = {
|
|
{CKA_VALUE, secretA_value, sizeof(secretA_value)}
|
|
};
|
|
CK_ULONG secretA_tmpl_len = sizeof(secretA_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_ATTRIBUTE secretB_tmpl[] = {
|
|
{CKA_VALUE, secretB_value, sizeof(secretB_value)}
|
|
};
|
|
CK_ULONG secretB_tmpl_len = sizeof(secretB_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_BBOOL extractable = !pkey;
|
|
CK_ATTRIBUTE derive_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE, &secret_key_type, sizeof(secret_key_type)},
|
|
{CKA_VALUE_LEN, &(ecdh_tv[i].derived_key_len), sizeof(CK_ULONG)},
|
|
{CKA_SENSITIVE, &false, sizeof(false)},
|
|
{CKA_EXTRACTABLE, &extractable, sizeof(CK_BBOOL)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &pkey, sizeof(CK_BBOOL)},
|
|
};
|
|
CK_ULONG derive_tmpl_len = sizeof(derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
// Now, derive a generic secret key using party A's private key
|
|
// and B's public key
|
|
ecdh_parmA.kdf = ecdh_tv[i].kdf;
|
|
ecdh_parmA.pPublicData = ecdh_tv[i].pubkeyB;
|
|
ecdh_parmA.ulPublicDataLen = ecdh_tv[i].pubkey_len;
|
|
ecdh_parmA.pSharedData =
|
|
ecdh_tv[i].shared_data_len == 0 ?
|
|
NULL : (CK_BYTE_PTR)&ecdh_tv[i].shared_data;
|
|
ecdh_parmA.ulSharedDataLen = ecdh_tv[i].shared_data_len;
|
|
|
|
if (ecdh_tv[i].kdf == CKD_NULL) {
|
|
ecdh_parmA.pSharedData = NULL;
|
|
ecdh_parmA.ulSharedDataLen = 0;
|
|
}
|
|
|
|
mech.mechanism = CKM_ECDH1_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parmA;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
priv_keyA, derive_tmpl,
|
|
derive_tmpl_len, &secret_keyA);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
} else if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
(ecdh_tv[i].kdf != CKD_NULL ||
|
|
ecdh_tv[i].shared_data_len > 0)) {
|
|
testcase_skip("EP11 does not support KDF %s and/or shared data "
|
|
"with older firmware versions\n",
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
continue;
|
|
} else if (is_icsf_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
ecdh_tv[i].kdf != CKD_NULL &&
|
|
ecdh_tv[i].kdf != CKD_SHA224_KDF &&
|
|
ecdh_tv[i].kdf != CKD_SHA256_KDF &&
|
|
ecdh_tv[i].kdf != CKD_SHA384_KDF &&
|
|
ecdh_tv[i].kdf != CKD_SHA512_KDF) {
|
|
testcase_skip("ICSF does not support KDF %s\n",
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_DeriveKey #1: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Now, derive a generic secret key using B's private key and
|
|
// A's public key
|
|
ecdh_parmB.kdf = ecdh_tv[i].kdf;
|
|
ecdh_parmB.pPublicData = ecdh_tv[i].pubkeyA;
|
|
ecdh_parmB.ulPublicDataLen = ecdh_tv[i].pubkey_len;
|
|
ecdh_parmB.pSharedData =
|
|
ecdh_tv[i].shared_data_len == 0 ?
|
|
NULL : (CK_BYTE_PTR)&ecdh_tv[i].shared_data;
|
|
ecdh_parmB.ulSharedDataLen = ecdh_tv[i].shared_data_len;
|
|
|
|
if (ecdh_tv[i].kdf == CKD_NULL) {
|
|
ecdh_parmB.pSharedData = NULL;
|
|
ecdh_parmB.ulSharedDataLen = 0;
|
|
}
|
|
|
|
mech.mechanism = CKM_ECDH1_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parmB;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
priv_keyB, derive_tmpl,
|
|
derive_tmpl_len, &secret_keyB);
|
|
if (rc != CKR_OK) {
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
(ecdh_tv[i].kdf != CKD_NULL ||
|
|
ecdh_tv[i].shared_data_len > 0)) {
|
|
testcase_skip("EP11 does not support KDF %s and/or shared data "
|
|
"with older firmware versions\n",
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
continue;
|
|
} else if (is_icsf_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
ecdh_tv[i].kdf != CKD_NULL &&
|
|
ecdh_tv[i].kdf != CKD_SHA224_KDF &&
|
|
ecdh_tv[i].kdf != CKD_SHA256_KDF &&
|
|
ecdh_tv[i].kdf != CKD_SHA384_KDF &&
|
|
ecdh_tv[i].kdf != CKD_SHA512_KDF) {
|
|
testcase_skip("ICSF does not support KDF %s\n",
|
|
p11_get_ckd(ecdh_tv[i].kdf));
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_DeriveKey #2: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
|
|
/* A secure key token won't reveal the key value in clear */
|
|
if (!is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
// Extract the derived secret A
|
|
rc = funcs->C_GetAttributeValue(session, secret_keyA,
|
|
secretA_tmpl, secretA_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #3:rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare lengths of derived secret from key object
|
|
if (ecdh_tv[i].derived_key_len != secretA_tmpl[0].ulValueLen) {
|
|
testcase_fail("ERROR:derived key #1 length = %lu, "
|
|
"derived key #2 length = %lu",
|
|
ecdh_tv[i].derived_key_len,
|
|
secretA_tmpl[0].ulValueLen);
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare with known value
|
|
if (memcmp(secretA_tmpl[0].pValue,
|
|
ecdh_tv[i].derived_key,
|
|
ecdh_tv[i].derived_key_len) != 0) {
|
|
testcase_fail("ERROR:derived key mismatch, i=%lu",i);
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Extract the derived secret B
|
|
rc = funcs->C_GetAttributeValue(session, secret_keyB,
|
|
secretB_tmpl, secretB_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #4:rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare lengths of derived secret from key object
|
|
if (ecdh_tv[i].derived_key_len != secretB_tmpl[0].ulValueLen) {
|
|
testcase_fail("ERROR:derived key #1 length = %lu, derived key "
|
|
"#2 length = %lu", ecdh_tv[i].derived_key_len,
|
|
secretB_tmpl[0].ulValueLen);
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare with known value
|
|
if (memcmp(secretB_tmpl[0].pValue,
|
|
ecdh_tv[i].derived_key,
|
|
ecdh_tv[i].derived_key_len) != 0) {
|
|
testcase_fail("ERROR:derived key mismatch, i=%lu",i);
|
|
goto testcase_next;
|
|
}
|
|
} else {
|
|
/* Secure key:
|
|
* Calculate HMAC with derived keys and expected key and compare
|
|
* the MAC.
|
|
*/
|
|
rc = run_HMACSign_OpenSSL(ecdh_tv[i].derived_key,
|
|
ecdh_tv[i].derived_key_len,
|
|
CKM_SHA_1_HMAC,
|
|
macexpected, &macexpected_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("HMAC for expected key failed: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = run_HMACSign(session, secret_keyA, ecdh_tv[i].derived_key_len,
|
|
CKM_SHA_1_HMAC, mac1, &mac1_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("HMAC for derived key #1 failed: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
if (mac1_len != 0 && /* skip check if mac can't be calcualted */
|
|
(mac1_len != macexpected_len ||
|
|
memcmp(mac1, macexpected, mac1_len) != 0)) {
|
|
testcase_fail("ERROR: derived key #1 does not produce the "
|
|
"expected HMAC");
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = run_HMACSign(session, secret_keyB, ecdh_tv[i].derived_key_len,
|
|
CKM_SHA_1_HMAC, mac2, &mac2_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("HMAC for derived key #2 failed: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
if (mac2_len != 0 && /* skip check if mac can't be calcualted */
|
|
(mac2_len != macexpected_len ||
|
|
memcmp(mac2, macexpected, mac2_len) != 0)) {
|
|
testcase_fail("ERROR: derived key #2 does not produce the "
|
|
"expected HMAC");
|
|
goto testcase_next;
|
|
}
|
|
}
|
|
|
|
testcase_pass("*Derive shared secret i=%lu passed.", i);
|
|
|
|
testcase_next:
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
} /* end run_DeriveECDHKeyKAT() */
|
|
|
|
CK_RV run_GenerateSignVerifyECC(CK_SESSION_HANDLE session,
|
|
CK_MECHANISM *mech,
|
|
CK_ULONG inputlen,
|
|
CK_ULONG parts,
|
|
CK_OBJECT_HANDLE priv_key,
|
|
CK_OBJECT_HANDLE publ_key,
|
|
enum curve_type curve_type,
|
|
CK_BYTE *params, CK_ULONG params_len)
|
|
{
|
|
CK_BYTE_PTR data = NULL, signature = NULL;
|
|
CK_ULONG i, signaturelen;
|
|
CK_MECHANISM_INFO mech_info;
|
|
CK_RV rc;
|
|
|
|
if ((mech->mechanism == CKM_IBM_ED25519_SHA512 ||
|
|
mech->mechanism == CKM_IBM_ED448_SHA3)) {
|
|
if (curve_type != CURVE_EDWARDS) {
|
|
/* Mechanism does not match to curve type, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
if (mech->mechanism == CKM_IBM_ED25519_SHA512 &&
|
|
memcmp(params, ed25519, MIN(params_len, sizeof(ed25519))) != 0) {
|
|
/* Mechanism does not match to curve, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
if (mech->mechanism == CKM_IBM_ED448_SHA3 &&
|
|
memcmp(params, ed448, MIN(params_len, sizeof(ed448))) != 0) {
|
|
/* Mechanism does not match to curve, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
} else if (mech->mechanism == CKM_IBM_ECDSA_OTHER &&
|
|
memcmp(params, secp256k1, MIN(params_len, sizeof(secp256k1))) != 0 &&
|
|
memcmp(params, prime256v1, MIN(params_len, sizeof(prime256v1))) != 0 &&
|
|
memcmp(params, brainpoolP256r1, MIN(params_len, sizeof(brainpoolP256r1))) != 0 &&
|
|
memcmp(params, brainpoolP256t1, MIN(params_len, sizeof(brainpoolP256t1))) != 0 &&
|
|
memcmp(params, bls12_381, MIN(params_len, sizeof(bls12_381))) != 0) {
|
|
/* CKM_IBM_ECDSA_OTHER can only be used with 256-bit or BLS EC curves, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
} else if (mech->mechanism == CKM_IBM_ECDSA_OTHER &&
|
|
memcmp(params, bls12_381, MIN(params_len, sizeof(bls12_381))) == 0 &&
|
|
mech->pParameter != NULL &&
|
|
mech->ulParameterLen == sizeof(CK_IBM_ECDSA_OTHER_PARAMS) &&
|
|
((CK_IBM_ECDSA_OTHER_PARAMS *)mech->pParameter)->submechanism != CKM_IBM_BLS) {
|
|
/* ECDSA_OTHER: BLS curve can only be used with CKM_IBM_BLS sub mech, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
} else if (mech->mechanism == CKM_IBM_ECDSA_OTHER &&
|
|
memcmp(params, bls12_381, MIN(params_len, sizeof(bls12_381))) != 0 &&
|
|
mech->pParameter != NULL &&
|
|
mech->ulParameterLen == sizeof(CK_IBM_ECDSA_OTHER_PARAMS) &&
|
|
((CK_IBM_ECDSA_OTHER_PARAMS *)mech->pParameter)->submechanism == CKM_IBM_BLS) {
|
|
/* ECDSA_OTHER: Non-BLS curve can not be used with CKM_IBM_BLS sub mech, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
} else if (mech->mechanism == CKM_EDDSA) {
|
|
if (curve_type != CURVE_EDWARDS) {
|
|
/* Mechanism does not match to curve type, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (memcmp(params, ed448, MIN(params_len, sizeof(ed448))) == 0 &&
|
|
mech->pParameter == NULL) {
|
|
/* Ed448 requires a mechanism parameter, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
} else if (mech->mechanism != CKM_IBM_ED25519_SHA512 &&
|
|
mech->mechanism != CKM_IBM_ED448_SHA3 &&
|
|
mech->mechanism != CKM_IBM_ECDSA_OTHER &&
|
|
mech->mechanism != CKM_EDDSA) {
|
|
if (curve_type == CURVE_EDWARDS || curve_type == CURVE_MONTGOMERY ||
|
|
curve_type == CURVE_BLS12_381) {
|
|
/* Mechanism does not match to curve type, skip */
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
testcase_begin("Starting with mechtype='%s', inputlen=%lu parts=%lu, pkey=%X",
|
|
p11_get_ckm(&mechtable_funcs, mech->mechanism), inputlen, parts, pkey);
|
|
|
|
/* query the slot, check if this mech if supported */
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech->mechanism, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for EC key gen? skip */
|
|
testcase_skip("Slot %u doesn't support %s",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckm(&mechtable_funcs, mech->mechanism));
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
if (inputlen > 0) {
|
|
data = calloc(inputlen, sizeof(CK_BYTE));
|
|
if (data == NULL) {
|
|
testcase_error("Can't allocate memory for %lu bytes",
|
|
sizeof(CK_BYTE) * inputlen);
|
|
rc = -1;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (i = 0; i < inputlen; i++) {
|
|
data[i] = (i + 1) % 255;
|
|
}
|
|
}
|
|
|
|
rc = funcs->C_SignInit(session, mech, priv_key);
|
|
if (rc != CKR_OK) {
|
|
if (mech->mechanism == CKM_EDDSA && rc == CKR_MECHANISM_PARAM_INVALID) {
|
|
testcase_skip("EdDSA mechanism parameter combination is not "
|
|
"supported");
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (parts > 0) {
|
|
if (inputlen > 0) {
|
|
for (i = 0; i < parts && inputlen > 0; i++) {
|
|
rc = funcs->C_SignUpdate(session, data, inputlen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
} else {
|
|
rc = funcs->C_SignUpdate(session, NULL, 0);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
/* get signature length */
|
|
rc = funcs->C_SignFinal(session, signature, &signaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_SignFinal rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
} else {
|
|
rc = funcs->C_Sign(session, data != NULL ? data : (CK_BYTE *)"",
|
|
inputlen, NULL, &signaturelen);
|
|
if (rc != CKR_OK) {
|
|
if (mech->mechanism == CKM_EDDSA &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID) {
|
|
testcase_skip("EdDSA mechanism parameter combination is not "
|
|
"supported");
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
signature = calloc(signaturelen, sizeof(CK_BYTE));
|
|
if (signature == NULL) {
|
|
testcase_error("Can't allocate memory for %lu bytes",
|
|
sizeof(CK_BYTE) * signaturelen);
|
|
rc = -1;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (parts > 0) {
|
|
rc = funcs->C_SignFinal(session, signature, &signaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_SignFinal rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
} else {
|
|
rc = funcs->C_Sign(session, data != NULL ? data : (CK_BYTE *)"",
|
|
inputlen, signature, &signaturelen);
|
|
if (rc != CKR_OK) {
|
|
if (mech->mechanism == CKM_EDDSA &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID) {
|
|
testcase_skip("EdDSA mechanism parameter combination is not "
|
|
"supported");
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
/****** Verify *******/
|
|
rc = funcs->C_VerifyInit(session, mech, publ_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (parts > 0) {
|
|
if (inputlen > 0) {
|
|
for (i = 0; i < parts && inputlen > 0; i++) {
|
|
rc = funcs->C_VerifyUpdate(session, data, inputlen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
} else {
|
|
rc = funcs->C_VerifyUpdate(session, NULL, 0);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
rc = funcs->C_VerifyFinal(session, signature, signaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyFinal rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
} else {
|
|
rc = funcs->C_Verify(session, data != NULL ? data : (CK_BYTE *)"",
|
|
inputlen, signature, signaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
// corrupt the signature and re-verify
|
|
memcpy(signature, "ABCDEFGHIJKLMNOPQRSTUV",
|
|
strlen("ABCDEFGHIJKLMNOPQRSTUV"));
|
|
|
|
rc = funcs->C_VerifyInit(session, mech, publ_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (parts > 0) {
|
|
if (inputlen > 0) {
|
|
for (i = 0; i < parts && inputlen > 0; i++) {
|
|
rc = funcs->C_VerifyUpdate(session, data, inputlen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
} else {
|
|
rc = funcs->C_VerifyUpdate(session, NULL, 0);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
rc = funcs->C_VerifyFinal(session, signature, signaturelen);
|
|
if (rc != CKR_SIGNATURE_INVALID) {
|
|
if (rc == CKR_FUNCTION_FAILED && is_ica_token(SLOT_ID)) {
|
|
testcase_notice("C_VerifyFinal rc=%s temporarily accepted for ICA token",
|
|
p11_get_ckr(rc));
|
|
} else {
|
|
testcase_error("C_VerifyFinal rc=%s", p11_get_ckr(rc));
|
|
PRINT_ERR(" Expected CKR_SIGNATURE_INVALID\n");
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
} else {
|
|
rc = funcs->C_Verify(session, data != NULL ? data : (CK_BYTE *)"",
|
|
inputlen, signature, signaturelen);
|
|
if (rc != CKR_SIGNATURE_INVALID) {
|
|
if (rc == CKR_FUNCTION_FAILED && is_ica_token(SLOT_ID)) {
|
|
testcase_notice("C_Verify rc=%s temporarily accepted for ICA token",
|
|
p11_get_ckr(rc));
|
|
} else {
|
|
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
PRINT_ERR(" Expected CKR_SIGNATURE_INVALID\n");
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
rc = CKR_OK;
|
|
|
|
testcase_cleanup:
|
|
if (data)
|
|
free(data);
|
|
if (signature)
|
|
free(signature);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV run_GenerateECCKeyPairSignVerify(void)
|
|
{
|
|
CK_MECHANISM mech;
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len, i, j;
|
|
CK_FLAGS flags;
|
|
CK_MECHANISM_INFO mech_info;
|
|
CK_RV rc;
|
|
|
|
testcase_begin("Starting ECC generate key pair with pkey=%X ...", pkey);
|
|
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
mech.mechanism = CKM_EC_KEY_PAIR_GEN;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
/* query the slot, check if this mech is supported */
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for EC key gen? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_EC_KEY_PAIR_GEN",
|
|
(unsigned int) SLOT_ID);
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < NUMEC; i++) {
|
|
|
|
if (der_ec_supported[i].type == CURVE_MONTGOMERY) {
|
|
/* Montgomery curves can not be used for sign/verify. */
|
|
continue;
|
|
}
|
|
|
|
if (is_cca_token(SLOT_ID)) {
|
|
if (der_ec_supported[i].twisted) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
if (der_ec_supported[i].type != CURVE_BRAINPOOL &&
|
|
der_ec_supported[i].type != CURVE_PRIME &&
|
|
der_ec_supported[i].type != CURVE_KOBLITZ) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
}
|
|
if (is_icsf_token(SLOT_ID)) {
|
|
if (der_ec_supported[i].twisted ||
|
|
der_ec_supported[i].type == CURVE_EDWARDS ||
|
|
der_ec_supported[i].type == CURVE_BLS12_381) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
rc = generate_EC_KeyPair(session, CKM_EC_KEY_PAIR_GEN,
|
|
(CK_BYTE *)der_ec_supported[i].curve,
|
|
der_ec_supported[i].size,
|
|
&publ_key, &priv_key, !pkey);
|
|
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
continue;
|
|
}
|
|
testcase_fail
|
|
("generate_EC_KeyPair with valid input failed at i=%lu (%s), "
|
|
"rc=%s", i, der_ec_supported[i].name, p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Generate supported key pair index=%lu (%s) passed.", i,
|
|
der_ec_supported[i].name);
|
|
|
|
for (j = 0;
|
|
j < (sizeof(signVerifyInput) / sizeof(_signVerifyParam)); j++) {
|
|
testcase_new_assertion();
|
|
rc = run_GenerateSignVerifyECC(session,
|
|
&signVerifyInput[j].mech,
|
|
signVerifyInput[j].inputlen,
|
|
signVerifyInput[j].parts,
|
|
priv_key, publ_key,
|
|
der_ec_supported[i].type,
|
|
(CK_BYTE *)der_ec_supported[i].curve,
|
|
der_ec_supported[i].size);
|
|
if (rc != 0) {
|
|
testcase_fail("run_GenerateSignVerifyECC failed index=%lu. i=%lu.", j, i);
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_pass("*Sign & verify i=%lu (%s), j=%lu passed.", i,
|
|
der_ec_supported[i].name, j);
|
|
}
|
|
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
publ_key = CK_INVALID_HANDLE;
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
priv_key = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
for (i = 0; i < NUMECINVAL; i++) {
|
|
rc = generate_EC_KeyPair(session, CKM_EC_KEY_PAIR_GEN,
|
|
(CK_BYTE *)der_ec_notsupported[i].curve,
|
|
der_ec_notsupported[i].size,
|
|
&publ_key, &priv_key, !pkey);
|
|
testcase_new_assertion();
|
|
if (rc == CKR_OK) {
|
|
testcase_fail
|
|
("generate_EC_KeyPair with invalid input failed at i=%lu (%s)",
|
|
i, der_ec_notsupported[i].name);
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_pass("*Generate unsupported key pair curve=%s passed.",
|
|
der_ec_notsupported[i].name);
|
|
}
|
|
|
|
rc = CKR_OK;
|
|
|
|
testcase_cleanup:
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV run_ImportECCKeyPairSignVerify(void)
|
|
{
|
|
CK_MECHANISM mech;
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len, i, j;
|
|
CK_FLAGS flags;
|
|
CK_MECHANISM_INFO mech_info;
|
|
CK_RV rc;
|
|
|
|
testcase_begin("Starting ECC import key pair with pkey=%X ...", pkey);
|
|
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
mech.mechanism = CKM_ECDSA;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
/* query the slot, check if this mech is supported */
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for EC key gen? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_ECDSA",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < EC_TV_NUM; i++) {
|
|
if ((is_ica_token(SLOT_ID) || is_cca_token(SLOT_ID) ||
|
|
is_icsf_token(SLOT_ID))) {
|
|
if (!curve_supported((char *)ec_tv[i].name)) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int)SLOT_ID,ec_tv[i].name);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (ec_tv[i].curve_type == CURVE_MONTGOMERY) {
|
|
/* Sign/verify not supported for the curve. */
|
|
continue;
|
|
}
|
|
|
|
if (ec_tv[i].curve_type == CURVE_EDWARDS) {
|
|
if (memcmp(ec_tv[i].name, "ed25519", 7) == 0) {
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_ED25519_SHA512)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_ED25519_SHA512\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
} else if (memcmp(ec_tv[i].name, "ed448", 5) == 0) {
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_ED448_SHA3)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_ED448_SHA3\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
}
|
|
} else {
|
|
if (!mech_supported(SLOT_ID, CKM_ECDSA)) {
|
|
testcase_skip("Slot %u doesn't support CKM_ECDSA\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
rc = create_ECPrivateKey(session, CKK_EC,
|
|
ec_tv[i].params, ec_tv[i].params_len,
|
|
ec_tv[i].privkey, ec_tv[i].privkey_len,
|
|
&priv_key, !pkey, CK_FALSE);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
continue;
|
|
}
|
|
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
"older firmware versions",
|
|
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu "
|
|
"(%s), rc=%s", i, ec_tv[i].name, p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Import EC private key (%s) index=%lu passed.",
|
|
ec_tv[i].name, i);
|
|
|
|
rc = create_ECPublicKey(session, CKK_EC,
|
|
ec_tv[i].params, ec_tv[i].params_len,
|
|
ec_tv[i].pubkey, ec_tv[i].pubkey_len,
|
|
&publ_key, !pkey);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
"older firmware versions",
|
|
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu "
|
|
"(%s), rc=%s", i, ec_tv[i].name, p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Import EC public key (%s) index=%lu passed.",
|
|
ec_tv[i].name, i);
|
|
|
|
/* create signature with private key */
|
|
for (j = 0;
|
|
j < (sizeof(signVerifyInput) / sizeof(_signVerifyParam)); j++) {
|
|
testcase_new_assertion();
|
|
rc = run_GenerateSignVerifyECC(session,
|
|
&signVerifyInput[j].mech,
|
|
signVerifyInput[j].inputlen,
|
|
signVerifyInput[j].parts,
|
|
priv_key, publ_key,
|
|
ec_tv[i].curve_type,
|
|
ec_tv[i].params,
|
|
ec_tv[i].params_len);
|
|
if (rc != 0) {
|
|
testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j);
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_pass("*Sign & verify i=%lu, j=%lu passed.", i, j);
|
|
}
|
|
|
|
// clean up
|
|
rc = funcs->C_DestroyObject(session, publ_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
|
|
rc = funcs->C_DestroyObject(session, priv_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
}
|
|
|
|
goto done;
|
|
|
|
testcase_cleanup:
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
|
|
done:
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV run_TransferECCKeyPairSignVerify(void)
|
|
{
|
|
CK_MECHANISM mech;
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len, i, j;
|
|
CK_FLAGS flags;
|
|
CK_MECHANISM_INFO mech_info;
|
|
CK_RV rc;
|
|
CK_MECHANISM aes_keygen_mech;
|
|
CK_OBJECT_HANDLE secret_key = CK_INVALID_HANDLE;
|
|
CK_BYTE_PTR wrapped_key = NULL;
|
|
CK_ULONG wrapped_keylen;
|
|
CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE;
|
|
CK_MECHANISM wrap_mech;
|
|
|
|
testcase_begin("Starting ECC transfer key pair with pkey=%X ...", pkey);
|
|
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
mech.mechanism = CKM_ECDSA;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
/* query the slot, check if this mech is supported */
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for EC key gen? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_ECDSA",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_KEY_GEN, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for AES key gen? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_AES_KEY_GEN",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_CBC_PAD, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for AES CBC wrap? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
if ((mech_info.flags & CKF_WRAP) == 0 ||
|
|
(mech_info.flags & CKF_UNWRAP) == 0) {
|
|
/* no support for AES CBC wrap? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD for wrapping "
|
|
"keys", (unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (i = 0; i < EC_TV_NUM; i++) {
|
|
if (is_cca_token(SLOT_ID) || is_icsf_token(SLOT_ID)) {
|
|
if (strstr((char *)ec_tv[i].name, "t1") != NULL) {
|
|
testcase_skip("Slot %u doesn't support curve %s",
|
|
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
continue;
|
|
}
|
|
if (ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
ec_tv[i].curve_type == CURVE_MONTGOMERY ||
|
|
ec_tv[i].curve_type == CURVE_BLS12_381) {
|
|
testcase_skip("Slot %u doesn't support curve %s",
|
|
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (ec_tv[i].curve_type == CURVE_MONTGOMERY) {
|
|
/* Sign/verify not supported for the curve. */
|
|
continue;
|
|
}
|
|
|
|
if (ec_tv[i].curve_type == CURVE_EDWARDS) {
|
|
if (memcmp(ec_tv[i].name, "ed25519", 7) == 0) {
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_ED25519_SHA512)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_ED25519_SHA512\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
} else if (memcmp(ec_tv[i].name, "ed448", 5) == 0) {
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_ED448_SHA3)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_ED448_SHA3\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
}
|
|
} else {
|
|
if (!mech_supported(SLOT_ID, CKM_ECDSA)) {
|
|
testcase_skip("Slot %u doesn't support CKM_ECDSA\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
rc = create_ECPrivateKey(session, CKK_EC,
|
|
ec_tv[i].params, ec_tv[i].params_len,
|
|
ec_tv[i].privkey, ec_tv[i].privkey_len,
|
|
&priv_key, CK_TRUE, // key to be wrapped must be extractable
|
|
CK_FALSE);
|
|
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
continue;
|
|
}
|
|
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
"older firmware versions",
|
|
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
continue;
|
|
}
|
|
|
|
testcase_fail
|
|
("C_CreateObject (EC Private Key) failed at i=%lu, rc=%s", i,
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Import EC private key (%s) index=%lu passed.",
|
|
ec_tv[i].name, i);
|
|
|
|
rc = create_ECPublicKey(session, CKK_EC,
|
|
ec_tv[i].params, ec_tv[i].params_len,
|
|
ec_tv[i].pubkey, ec_tv[i].pubkey_len,
|
|
&publ_key, !pkey);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
"older firmware versions",
|
|
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
|
|
testcase_fail
|
|
("C_CreateObject (EC Public Key) failed at i=%lu, rc=%s", i,
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Import EC public key (%s) index=%lu passed.",
|
|
ec_tv[i].name, i);
|
|
|
|
/* create wrapping key (secret key) */
|
|
aes_keygen_mech.mechanism = CKM_AES_KEY_GEN;
|
|
|
|
CK_OBJECT_CLASS wkclass = CKO_SECRET_KEY;
|
|
CK_ULONG keylen = 32;
|
|
CK_BBOOL true = TRUE;
|
|
CK_BBOOL false = FALSE;
|
|
CK_BBOOL sign = TRUE;
|
|
CK_BBOOL derive = TRUE;
|
|
CK_BYTE wrap_key_label[] = "Wrap_Key";
|
|
CK_OBJECT_CLASS wclass = CKO_PRIVATE_KEY;
|
|
CK_KEY_TYPE keyType = CKK_EC;
|
|
CK_ATTRIBUTE cka_wrap_tmpl[] = {
|
|
{CKA_PRIVATE, &true, sizeof(true)},
|
|
{CKA_CLASS, &wclass, sizeof(wclass)},
|
|
{CKA_KEY_TYPE, &keyType, sizeof(keyType)},
|
|
};
|
|
CK_ATTRIBUTE cka_unwrap_tmpl[] = {
|
|
{CKA_DECRYPT, &true, sizeof(true)},
|
|
{CKA_SIGN, &sign, sizeof(sign)},
|
|
{CKA_DERIVE, &derive, sizeof(derive)},
|
|
{CKA_PRIVATE, &true, sizeof(true)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &true, sizeof(true)},
|
|
{CKA_EXTRACTABLE, &false, sizeof(false)},
|
|
};
|
|
CK_ATTRIBUTE secret_tmpl[] = {
|
|
{CKA_CLASS, &wkclass, sizeof(wkclass)},
|
|
{CKA_VALUE_LEN, &keylen, sizeof(keylen)},
|
|
{CKA_LABEL, &wrap_key_label, sizeof(wrap_key_label)},
|
|
{CKA_TOKEN, &true, sizeof(true)},
|
|
{CKA_WRAP, &true, sizeof(true)},
|
|
{CKA_UNWRAP, &true, sizeof(true)},
|
|
{CKA_WRAP_TEMPLATE, &cka_wrap_tmpl, sizeof(cka_wrap_tmpl)},
|
|
{CKA_UNWRAP_TEMPLATE, &cka_unwrap_tmpl, sizeof(cka_unwrap_tmpl)},
|
|
};
|
|
CK_ULONG secret_tmpl_len = sizeof(secret_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
if (ec_tv[i].curve_type == CURVE_EDWARDS)
|
|
derive = FALSE;
|
|
if (ec_tv[i].curve_type == CURVE_MONTGOMERY)
|
|
sign = FALSE;
|
|
if (ec_tv[i].curve_type == CURVE_BLS12_381) {
|
|
sign = TRUE;
|
|
derive = TRUE;
|
|
}
|
|
|
|
if (is_icsf_token(SLOT_ID))
|
|
secret_tmpl_len -= 2; /* ICSF does not support array-attributes */
|
|
|
|
rc = funcs->C_GenerateKey(session, &aes_keygen_mech, secret_tmpl,
|
|
secret_tmpl_len, &secret_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GenerateKey, rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
/* wrap/unwrap private and public EC key with a transport key */
|
|
|
|
// length only
|
|
wrap_mech.mechanism = CKM_AES_CBC_PAD;
|
|
wrap_mech.pParameter = "0123456789abcdef";
|
|
wrap_mech.ulParameterLen = 16;
|
|
rc = funcs->C_WrapKey(session, &wrap_mech, secret_key, priv_key,
|
|
NULL, &wrapped_keylen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_WrapKey(), rc=%s.", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
// allocate memory for wrapped_key
|
|
wrapped_key = calloc(wrapped_keylen, sizeof(CK_BYTE));
|
|
if (wrapped_key == NULL) {
|
|
testcase_error("Can't allocate memory for %lu bytes.",
|
|
sizeof(CK_BYTE) * wrapped_keylen);
|
|
rc = CKR_HOST_MEMORY;
|
|
goto testcase_cleanup;
|
|
}
|
|
// wrap key
|
|
//
|
|
rc = funcs->C_WrapKey(session, &wrap_mech, secret_key, priv_key,
|
|
wrapped_key, &wrapped_keylen);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_WrapKey, rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
// unwrap key
|
|
//
|
|
CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
|
|
CK_KEY_TYPE key_type = CKK_EC;
|
|
CK_BYTE unwrap_label[] = "unwrapped_private_EC_Key";
|
|
CK_BYTE id[] = { 123 };
|
|
|
|
CK_ATTRIBUTE unwrap_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_TOKEN, &true, sizeof(true)},
|
|
{CKA_LABEL, &unwrap_label, sizeof(unwrap_label)},
|
|
{CKA_ID, id, sizeof(id)},
|
|
{CKA_SENSITIVE, &true, sizeof(true)},
|
|
{CKA_DERIVE, &derive, sizeof(derive)},
|
|
{CKA_SIGN, &sign, sizeof(sign)},
|
|
{CKA_EXTRACTABLE, &false, sizeof(false)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG unwrap_tmpl_len = sizeof(unwrap_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE unwrap_base_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_DERIVE, &derive, sizeof(derive)},
|
|
{CKA_SIGN, &sign, sizeof(sign)},
|
|
};
|
|
|
|
if (is_icsf_token(SLOT_ID))
|
|
unwrap_tmpl_len -= 1; /* ICSF does not supp. CKA_IBM_PROTKEY_... */
|
|
|
|
rc = funcs->C_UnwrapKey(session, &wrap_mech, secret_key,
|
|
wrapped_key, wrapped_keylen,
|
|
unwrap_tmpl, unwrap_tmpl_len,
|
|
&unwrapped_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_UnwrapKey, rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// unwrap again with each CKA_SENSITIVE / CKA_EXTRACTABLE choice; the
|
|
// transport key's CKA_UNWRAP_TEMPLATE sets CKA_EXTRACTABLE = FALSE
|
|
// (except on ICSF, which gets no array attributes)
|
|
rc = check_unwrap_sensitive_extractable(session, &wrap_mech,
|
|
secret_key, wrapped_key, wrapped_keylen, unwrap_base_tmpl,
|
|
sizeof(unwrap_base_tmpl) / sizeof(CK_ATTRIBUTE),
|
|
CKA_VALUE, NULL,
|
|
is_icsf_token(SLOT_ID) ? NULL : &false);
|
|
if (rc != CKR_OK)
|
|
goto testcase_cleanup;
|
|
|
|
if (wrapped_key) {
|
|
free(wrapped_key);
|
|
wrapped_key = NULL;
|
|
}
|
|
|
|
/* create signature with unwrapped private key and verify with
|
|
* public key */
|
|
for (j = 0;
|
|
j < (sizeof(signVerifyInput) / sizeof(_signVerifyParam)); j++) {
|
|
testcase_new_assertion();
|
|
rc = run_GenerateSignVerifyECC(session,
|
|
&signVerifyInput[j].mech,
|
|
signVerifyInput[j].inputlen,
|
|
signVerifyInput[j].parts,
|
|
unwrapped_key, publ_key,
|
|
ec_tv[i].curve_type,
|
|
ec_tv[i].params,
|
|
ec_tv[i].params_len);
|
|
if (rc != 0) {
|
|
testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j);
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_pass("*Sign & verify i=%lu, j=%lu passed.", i, j);
|
|
}
|
|
|
|
// clean up
|
|
rc = funcs->C_DestroyObject(session, publ_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
|
|
rc = funcs->C_DestroyObject(session, priv_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
|
|
rc = funcs->C_DestroyObject(session, secret_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
rc = funcs->C_DestroyObject(session, unwrapped_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
}
|
|
|
|
goto done;
|
|
|
|
testcase_cleanup:
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
if (secret_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_key);
|
|
if (unwrapped_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, unwrapped_key);
|
|
|
|
if (wrapped_key)
|
|
free(wrapped_key);
|
|
|
|
done:
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Tests the EP11 token protected key option. PKEY_MODE ENABLE4NONEXTR must be
|
|
* set in ep11tok.conf in order to activate protected key support. With MSA9,
|
|
* ECDSA with curves p256, p384, p521, and EDDSA with curves ed25519, and
|
|
* ed448 are supported via CPACF. On older machines there is no CPACF support
|
|
* for EC/ED at all and therefore all tests are performed only via the ep11
|
|
* card. So the actual behavior of this testcase heavily depends on the
|
|
* machine and token config.
|
|
*/
|
|
CK_RV run_ImportSignVerify_Pkey(void)
|
|
{
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len;
|
|
CK_FLAGS flags;
|
|
CK_RV rc;
|
|
CK_OBJECT_CLASS class;
|
|
CK_KEY_TYPE keytype = CKK_EC;
|
|
CK_BBOOL true = TRUE;
|
|
CK_BBOOL extr_priv, pkey_extr_priv, pkey_extr_pub;
|
|
CK_MECHANISM ec_mech = {CKM_ECDSA, NULL, 0};
|
|
CK_MECHANISM ed25519_mech = {CKM_IBM_ED25519_SHA512, NULL, 0};
|
|
CK_MECHANISM ed448_mech = {CKM_IBM_ED448_SHA3, NULL, 0};
|
|
CK_BYTE data[] = {
|
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
|
|
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
|
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
|
};
|
|
CK_BYTE *sig = NULL;
|
|
CK_ULONG sig_len;
|
|
unsigned int i, j;
|
|
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (i = 0; i < EC_TV_NUM; i++) {
|
|
|
|
CK_ATTRIBUTE priv_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(CK_OBJECT_CLASS)},
|
|
{CKA_KEY_TYPE, &keytype, sizeof(CK_KEY_TYPE)},
|
|
{CKA_PRIVATE, &true, sizeof(CK_BBOOL)},
|
|
{CKA_SIGN, &true, sizeof(CK_BBOOL)},
|
|
{CKA_EC_PARAMS, ec_tv[i].params, ec_tv[i].params_len},
|
|
{CKA_EC_POINT, ec_tv[i].pubkey, ec_tv[i].pubkey_len},
|
|
{CKA_VALUE, ec_tv[i].privkey, ec_tv[i].privkey_len},
|
|
{CKA_EXTRACTABLE, &extr_priv, sizeof(CK_BBOOL)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &pkey_extr_priv, sizeof(CK_BBOOL)},
|
|
};
|
|
CK_ATTRIBUTE publ_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(CK_OBJECT_CLASS)},
|
|
{CKA_KEY_TYPE, &keytype, sizeof(CK_KEY_TYPE)},
|
|
{CKA_VERIFY, &true, sizeof(CK_BBOOL)},
|
|
{CKA_EC_PARAMS, ec_tv[i].params, ec_tv[i].params_len},
|
|
{CKA_EC_POINT, ec_tv[i].pubkey, ec_tv[i].pubkey_len},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &pkey_extr_pub, sizeof(CK_BBOOL)},
|
|
};
|
|
|
|
if (ec_tv[i].curve_type == CURVE_MONTGOMERY) {
|
|
/* Sign/verify not supported for the curve. */
|
|
continue;
|
|
}
|
|
|
|
if (ec_tv[i].curve_type == CURVE_EDWARDS) {
|
|
if (memcmp(ec_tv[i].name, "ed25519", 7) == 0) {
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_ED25519_SHA512)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_ED25519_SHA512\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
} else if (memcmp(ec_tv[i].name, "ed448", 5) == 0) {
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_ED448_SHA3)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_ED448_SHA3\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
}
|
|
} else {
|
|
if (!mech_supported(SLOT_ID, CKM_ECDSA)) {
|
|
testcase_skip("Slot %u doesn't support CKM_ECDSA\n",
|
|
(unsigned int) SLOT_ID);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
if (ec_tv[i].curve_type == CURVE_BLS12_381) {
|
|
/* BLS does not use protected keys, skip */
|
|
continue;
|
|
}
|
|
|
|
if (j == 0)
|
|
testcase_begin("Starting Import EC private key (%s) index=%u sign via CPACF / verify via card",
|
|
ec_tv[i].name, i);
|
|
else
|
|
testcase_begin("Starting Import EC private key (%s) index=%u sign via card / verify via CPACF",
|
|
ec_tv[i].name, i);
|
|
|
|
/* j toggles between sign via protected key / verify via card
|
|
* and vice versa. */
|
|
if (j == 0) {
|
|
extr_priv = FALSE;
|
|
pkey_extr_priv = TRUE;
|
|
pkey_extr_pub = FALSE;
|
|
} else {
|
|
extr_priv = TRUE;
|
|
pkey_extr_priv = FALSE;
|
|
pkey_extr_pub = TRUE;
|
|
}
|
|
|
|
class = CKO_PRIVATE_KEY;
|
|
rc = funcs->C_CreateObject(session, priv_tmpl,
|
|
sizeof(priv_tmpl) / sizeof(CK_ATTRIBUTE),
|
|
&priv_key);
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
continue;
|
|
}
|
|
testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
class = CKO_PUBLIC_KEY;
|
|
rc = funcs->C_CreateObject(session, publ_tmpl,
|
|
sizeof(publ_tmpl) / sizeof(CK_ATTRIBUTE),
|
|
&publ_key);
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (ec_tv[i].curve_type != CURVE_EDWARDS &&
|
|
ec_tv[i].curve_type != CURVE_MONTGOMERY)
|
|
rc = funcs->C_SignInit(session, &ec_mech, priv_key);
|
|
else if (memcmp(ec_tv[i].name, "ed25519", 7) == 0)
|
|
rc = funcs->C_SignInit(session, &ed25519_mech, priv_key);
|
|
else if (memcmp(ec_tv[i].name, "ed448", 5) == 0)
|
|
rc = funcs->C_SignInit(session, &ed448_mech, priv_key);
|
|
else {
|
|
/* Sign/verify not supported for the curve. */
|
|
continue;
|
|
}
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
|
|
rc = funcs->C_Sign(session, data, sizeof(data), NULL, &sig_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
sig = calloc(sig_len, sizeof(CK_BYTE));
|
|
if (sig == NULL) {
|
|
testcase_error("Can't allocate memory for %lu bytes", sig_len);
|
|
rc = CKR_HOST_MEMORY;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Sign(session, data, sizeof(data), sig, &sig_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (ec_tv[i].curve_type != CURVE_EDWARDS &&
|
|
ec_tv[i].curve_type != CURVE_MONTGOMERY)
|
|
rc = funcs->C_VerifyInit(session, &ec_mech, publ_key);
|
|
else if (memcmp(ec_tv[i].name, "ed25519", 7) == 0)
|
|
rc = funcs->C_VerifyInit(session, &ed25519_mech, publ_key);
|
|
else
|
|
rc = funcs->C_VerifyInit(session, &ed448_mech, publ_key);
|
|
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Verify(session, data, sizeof(data), sig, sig_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (sig) {
|
|
free(sig);
|
|
sig = NULL;
|
|
}
|
|
|
|
if (j == 0)
|
|
testcase_pass("*Import EC private key (%s) index=%u sign via CPACF / verify via card passed.",
|
|
ec_tv[i].name, i);
|
|
else
|
|
testcase_pass("*Import EC private key (%s) index=%u sign via card / verify via CPACF passed.",
|
|
ec_tv[i].name, i);
|
|
}
|
|
}
|
|
|
|
rc = CKR_OK;
|
|
|
|
testcase_cleanup:
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
if (sig)
|
|
free(sig);
|
|
|
|
testcase_close_session();
|
|
return rc;
|
|
}
|
|
|
|
struct btc_test {
|
|
const _ec_struct ec;
|
|
CK_ULONG master_key_derive;
|
|
CK_ULONG priv_to_pub;
|
|
CK_ULONG priv_to_priv;
|
|
CK_ULONG pub_to_pub;
|
|
};
|
|
|
|
static const struct btc_test btc_tests[] = {
|
|
{ .ec = { &secp256k1, sizeof(secp256k1), CK_FALSE, CURVE_KOBLITZ,
|
|
CURVE256_LENGTH, "secp256k1" },
|
|
.master_key_derive = CK_IBM_BTC_BIP0032_MASTERK,
|
|
.priv_to_pub = CK_IBM_BTC_BIP0032_PRV2PUB,
|
|
.priv_to_priv = CK_IBM_BTC_BIP0032_PRV2PRV,
|
|
.pub_to_pub = CK_IBM_BTC_BIP0032_PUB2PUB,
|
|
},
|
|
{ .ec = { &secp256k1, sizeof(secp256k1), CK_FALSE, CURVE_KOBLITZ,
|
|
CURVE256_LENGTH, "secp256k1" },
|
|
.master_key_derive = CK_IBM_BTC_SLIP0010_MASTERK,
|
|
.priv_to_pub = CK_IBM_BTC_SLIP0010_PRV2PUB,
|
|
.priv_to_priv = CK_IBM_BTC_SLIP0010_PRV2PRV,
|
|
.pub_to_pub = CK_IBM_BTC_SLIP0010_PUB2PUB,
|
|
},
|
|
{ .ec = { &prime256v1, sizeof(prime256v1), CK_FALSE, CURVE_PRIME,
|
|
CURVE256_LENGTH, "prime256v1" },
|
|
.master_key_derive = CK_IBM_BTC_SLIP0010_MASTERK,
|
|
.priv_to_pub = CK_IBM_BTC_SLIP0010_PRV2PUB,
|
|
.priv_to_priv = CK_IBM_BTC_SLIP0010_PRV2PRV,
|
|
.pub_to_pub = CK_IBM_BTC_SLIP0010_PUB2PUB,
|
|
},
|
|
{ .ec = { &ed25519, sizeof(ed25519), CK_FALSE, CURVE_EDWARDS,
|
|
CURVE256_LENGTH, "ed25519" },
|
|
.master_key_derive = CK_IBM_BTC_SLIP0010_MASTERK,
|
|
.priv_to_pub = CK_IBM_BTC_SLIP0010_PRV2PUB,
|
|
.priv_to_priv = CK_IBM_BTC_SLIP0010_PRV2PRV,
|
|
.pub_to_pub = CK_IBM_BTC_SLIP0010_PUB2PUB,
|
|
},
|
|
};
|
|
|
|
#define NUM_BTC_TESTS 4
|
|
|
|
static const CK_ULONG btc_child_key_index[] = {
|
|
0,
|
|
0x12,
|
|
0x3456,
|
|
0x987654,
|
|
0x7fffffff,
|
|
0 + CK_IBM_BTC_BIP0032_HARDENED,
|
|
0x12 + CK_IBM_BTC_BIP0032_HARDENED,
|
|
0x3456 + CK_IBM_BTC_BIP0032_HARDENED,
|
|
0x987654 + CK_IBM_BTC_BIP0032_HARDENED,
|
|
0x7fffffff + CK_IBM_BTC_BIP0032_HARDENED,
|
|
};
|
|
|
|
#define NUM_BTC_CHILD_KEY_INDEXES 10
|
|
|
|
static const char *btc_type_to_str(CK_ULONG btc_type)
|
|
{
|
|
switch (btc_type) {
|
|
case CK_IBM_BTC_BIP0032_PRV2PRV:
|
|
return "CK_IBM_BTC_BIP0032_PRV2PRV";
|
|
case CK_IBM_BTC_BIP0032_PRV2PUB:
|
|
return "CK_IBM_BTC_BIP0032_PRV2PUB";
|
|
case CK_IBM_BTC_BIP0032_PUB2PUB:
|
|
return "CK_IBM_BTC_BIP0032_PUB2PUB";
|
|
case CK_IBM_BTC_BIP0032_MASTERK:
|
|
return "CK_IBM_BTC_BIP0032_MASTERK";
|
|
case CK_IBM_BTC_SLIP0010_PRV2PRV:
|
|
return "CK_IBM_BTC_SLIP0010_PRV2PRV";
|
|
case CK_IBM_BTC_SLIP0010_PRV2PUB:
|
|
return "CK_IBM_BTC_SLIP0010_PRV2PUB";
|
|
case CK_IBM_BTC_SLIP0010_PUB2PUB:
|
|
return "CK_IBM_BTC_SLIP0010_PUB2PUB";
|
|
case CK_IBM_BTC_SLIP0010_MASTERK:
|
|
return "CK_IBM_BTC_SLIP0010_MASTERK";
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Run Bitcoin Key Derivation tests:
|
|
* Derive a BTC master key from a generic secret key. Then derive a number of
|
|
* child keys (public and private, hardened and non hardened) from the master
|
|
* key.
|
|
*/
|
|
CK_RV run_DeriveBTC(void)
|
|
{
|
|
CK_SESSION_HANDLE session;
|
|
CK_MECHANISM mech;
|
|
CK_FLAGS flags;
|
|
CK_OBJECT_HANDLE secret = CK_INVALID_HANDLE, master = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE child_priv = CK_INVALID_HANDLE, child_pub = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE child_pub2 = CK_INVALID_HANDLE;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len;
|
|
CK_RV rc = CKR_OK;
|
|
CK_BBOOL true = CK_TRUE;
|
|
CK_IBM_BTC_DERIVE_PARAMS btc_parms;
|
|
CK_BYTE master_chain_code[CK_IBM_BTC_CHAINCODE_LENGTH];
|
|
CK_BYTE child_chain_code[CK_IBM_BTC_CHAINCODE_LENGTH];
|
|
CK_OBJECT_CLASS priv_class = CKO_PRIVATE_KEY;
|
|
CK_OBJECT_CLASS pub_class = CKO_PUBLIC_KEY;
|
|
CK_KEY_TYPE key_type = CKK_EC;
|
|
CK_OBJECT_CLASS secret_class = CKO_SECRET_KEY;
|
|
CK_ULONG secret_keylen = 32;
|
|
CK_ULONG i, k;
|
|
|
|
testsuite_begin("starting run_DeriveBTC with pkey=%X ...", pkey);
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
if (!mech_supported(SLOT_ID, CKM_GENERIC_SECRET_KEY_GEN)) {
|
|
testcase_skip("Slot %u doesn't support CKM_GENERIC_SECRET_KEY_GEN\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_BTC_DERIVE)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_BTC_DERIVE\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (i = 0; i < NUM_BTC_TESTS; i++) {
|
|
CK_ATTRIBUTE secret_tmpl[] = {
|
|
{CKA_CLASS, &secret_class, sizeof(secret_class)},
|
|
{CKA_VALUE_LEN, &secret_keylen, sizeof(secret_keylen)},
|
|
{CKA_IBM_USE_AS_DATA, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG secret_tmpl_len = sizeof(secret_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE priv_derive_tmpl[] = {
|
|
{CKA_CLASS, &priv_class, sizeof(priv_class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_DERIVE, &true, sizeof(true)},
|
|
{CKA_EC_PARAMS, (CK_VOID_PTR)btc_tests[i].ec.curve, btc_tests[i].ec.size},
|
|
{CKA_IBM_USE_AS_DATA, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG priv_derive_tmpl_len = sizeof(priv_derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE pub_derive_tmpl[] = {
|
|
{CKA_CLASS, &pub_class, sizeof(pub_class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_DERIVE, &true, sizeof(true)},
|
|
{CKA_EC_PARAMS, (CK_VOID_PTR)btc_tests[i].ec.curve, btc_tests[i].ec.size},
|
|
{CKA_IBM_USE_AS_DATA, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG pub_derive_tmpl_len = sizeof(pub_derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
/* Testcase #1: Derive the BTC master key from a secret key */
|
|
testcase_new_assertion();
|
|
testcase_begin("BTC master key derive with curve=%s and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name,
|
|
btc_type_to_str(btc_tests[i].master_key_derive), pkey);
|
|
|
|
mech.mechanism = CKM_GENERIC_SECRET_KEY_GEN;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
rc = funcs->C_GenerateKey(session, &mech, secret_tmpl, secret_tmpl_len,
|
|
&secret);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_GenerateKey, rc=%s", p11_get_ckr(rc));
|
|
goto run_cleanup;
|
|
}
|
|
|
|
mech.mechanism = CKM_IBM_BTC_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_BTC_DERIVE_PARAMS);
|
|
mech.pParameter = &btc_parms;
|
|
|
|
memset(master_chain_code, 0, sizeof(master_chain_code));
|
|
memset(&btc_parms, 0, sizeof(btc_parms));
|
|
btc_parms.version = CK_IBM_BTC_DERIVE_PARAMS_VERSION_1;
|
|
btc_parms.type = btc_tests[i].master_key_derive;
|
|
btc_parms.childKeyIndex = 0;
|
|
btc_parms.ulChainCodeLen = 0;
|
|
btc_parms.pChainCode = master_chain_code;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
secret, priv_derive_tmpl,
|
|
priv_derive_tmpl_len, &master);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey BTC master key: rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto run_cleanup;
|
|
}
|
|
|
|
testcase_pass("BTC master key derive with curve=%s and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name,
|
|
btc_type_to_str(btc_tests[i].master_key_derive), pkey);
|
|
|
|
/* Derive child keys from the master key */
|
|
for (k = 0; k < NUM_BTC_CHILD_KEY_INDEXES; k++) {
|
|
/* Testcase #2: Derive private child key from private master key */
|
|
|
|
/* For ed25519 only hardened child keys are supported (SLIP0010) */
|
|
if (btc_tests[i].master_key_derive == CK_IBM_BTC_SLIP0010_MASTERK &&
|
|
btc_tests[i].ec.type == CURVE_EDWARDS &&
|
|
(btc_child_key_index[k] & CK_IBM_BTC_BIP0032_HARDENED) == 0)
|
|
continue;
|
|
|
|
testcase_new_assertion();
|
|
testcase_begin("BTC priv-to-priv child key derive with curve=%s child-key-index=0x%lx and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name, btc_child_key_index[k],
|
|
btc_type_to_str(btc_tests[i].priv_to_priv), pkey);
|
|
|
|
mech.mechanism = CKM_IBM_BTC_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_BTC_DERIVE_PARAMS);
|
|
mech.pParameter = &btc_parms;
|
|
|
|
memcpy(child_chain_code, master_chain_code, sizeof(master_chain_code));
|
|
memset(&btc_parms, 0, sizeof(btc_parms));
|
|
btc_parms.version = CK_IBM_BTC_DERIVE_PARAMS_VERSION_1;
|
|
btc_parms.type = btc_tests[i].priv_to_priv;
|
|
btc_parms.childKeyIndex = btc_child_key_index[k];
|
|
btc_parms.ulChainCodeLen = sizeof(child_chain_code);
|
|
btc_parms.pChainCode = child_chain_code;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
master, priv_derive_tmpl,
|
|
priv_derive_tmpl_len, &child_priv);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey BTC child key (priv): rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto run_child_cleanup;
|
|
}
|
|
|
|
testcase_pass("BTC priv-to-priv child key derive with curve=%s child-key-index=0x%lx and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name, btc_child_key_index[k],
|
|
btc_type_to_str(btc_tests[i].priv_to_priv), pkey);
|
|
|
|
/* Testcase #3: Derive public child key from private master key */
|
|
testcase_new_assertion();
|
|
testcase_begin("BTC priv-to-pub child key derive with curve=%s child-key-index=0x%lx and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name, btc_child_key_index[k],
|
|
btc_type_to_str(btc_tests[i].priv_to_pub), pkey);
|
|
|
|
mech.mechanism = CKM_IBM_BTC_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_BTC_DERIVE_PARAMS);
|
|
mech.pParameter = &btc_parms;
|
|
|
|
memcpy(child_chain_code, master_chain_code, sizeof(master_chain_code));
|
|
memset(&btc_parms, 0, sizeof(btc_parms));
|
|
btc_parms.version = CK_IBM_BTC_DERIVE_PARAMS_VERSION_1;
|
|
btc_parms.type = btc_tests[i].priv_to_pub;
|
|
btc_parms.childKeyIndex = btc_child_key_index[k];
|
|
btc_parms.ulChainCodeLen = sizeof(child_chain_code);
|
|
btc_parms.pChainCode = child_chain_code;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
master, pub_derive_tmpl,
|
|
pub_derive_tmpl_len, &child_pub);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey BTC child key (pub): rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto run_child_cleanup;
|
|
}
|
|
|
|
testcase_pass("BTC priv-to-pub child key derive with curve=%s child-key-index=0x%lx and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name, btc_child_key_index[k],
|
|
btc_type_to_str(btc_tests[i].priv_to_pub), pkey);
|
|
|
|
/* Testcase #4: Test if derived keys are usable */
|
|
testcase_new_assertion();
|
|
|
|
if (btc_tests[i].ec.type == CURVE_EDWARDS)
|
|
mech.mechanism = CKM_IBM_ED25519_SHA512;
|
|
else
|
|
mech.mechanism = CKM_ECDSA;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
rc = run_GenerateSignVerifyECC(session, &mech, 20, 0,
|
|
child_priv, child_pub,
|
|
btc_tests[i].ec.type,
|
|
(CK_BYTE *)btc_tests[i].ec.curve,
|
|
btc_tests[i].ec.size);
|
|
if (rc != 0) {
|
|
testcase_fail("run_GenerateSignVerifyECC failed.");
|
|
goto run_child_cleanup;
|
|
}
|
|
testcase_pass("BTC check derived keys with curve=%s child-key-index=0x%lx, pkey=%X",
|
|
btc_tests[i].ec.name, btc_child_key_index[k], pkey);
|
|
|
|
/*
|
|
* Testcase #5: Derive public child key from public key
|
|
* (non-hardened keys only, thus not supported for ed25519)
|
|
*/
|
|
if ((btc_child_key_index[k] & CK_IBM_BTC_BIP0032_HARDENED) != 0)
|
|
goto run_child_cleanup;
|
|
|
|
testcase_new_assertion();
|
|
testcase_begin("BTC pub-to-pub child key derive with curve=%s child-key-index=0x%lx and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name, btc_child_key_index[k],
|
|
btc_type_to_str(btc_tests[i].pub_to_pub), pkey);
|
|
|
|
mech.mechanism = CKM_IBM_BTC_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_BTC_DERIVE_PARAMS);
|
|
mech.pParameter = &btc_parms;
|
|
|
|
memset(&btc_parms, 0, sizeof(btc_parms));
|
|
btc_parms.version = CK_IBM_BTC_DERIVE_PARAMS_VERSION_1;
|
|
btc_parms.type = btc_tests[i].pub_to_pub;
|
|
btc_parms.childKeyIndex = btc_child_key_index[k];
|
|
btc_parms.ulChainCodeLen = sizeof(child_chain_code);
|
|
btc_parms.pChainCode = child_chain_code;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
child_pub, pub_derive_tmpl,
|
|
pub_derive_tmpl_len, &child_pub2);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey BTC child key (pub): rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto run_child_cleanup;
|
|
}
|
|
|
|
testcase_pass("BTC pub-to-pub child key derive with curve=%s child-key-index=0x%lx and type=%s, pkey=%X",
|
|
btc_tests[i].ec.name, btc_child_key_index[k],
|
|
btc_type_to_str(btc_tests[i].pub_to_pub), pkey);
|
|
|
|
run_child_cleanup:
|
|
if (child_priv != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, child_priv);
|
|
child_priv = CK_INVALID_HANDLE;
|
|
if (child_pub != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, child_pub);
|
|
child_pub = CK_INVALID_HANDLE;
|
|
if (child_pub2 != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, child_pub2);
|
|
child_pub2 = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
run_cleanup:
|
|
if (secret != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret);
|
|
secret = CK_INVALID_HANDLE;
|
|
if (master != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, master);
|
|
master = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (secret != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret);
|
|
if (master != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, master);
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
} /* end run_DeriveBTC() */
|
|
|
|
_ec_struct bls_test = {&bls12_381, sizeof(bls12_381), CK_TRUE, CURVE_BLS12_381,
|
|
CURVE384_LENGTH, "bls12_381"};
|
|
|
|
_signVerifyParam bls_test_input = {{CKM_IBM_ECDSA_OTHER, &other_bls,
|
|
sizeof(other_bls)}, 20, 0, ""};
|
|
/*
|
|
* BLS test for Sign and derive
|
|
*/
|
|
CK_RV run_BLSAggregation(void)
|
|
{
|
|
CK_MECHANISM mech;
|
|
CK_OBJECT_HANDLE priv_key[CK_IBM_BLS_MAX_AGGREGATIONS] = { CK_INVALID_HANDLE },
|
|
pub_key[CK_IBM_BLS_MAX_AGGREGATIONS] = { CK_INVALID_HANDLE };
|
|
CK_IBM_ECDSA_OTHER_BLS_PARAMS blsparam1, blsparam2;
|
|
CK_OBJECT_HANDLE aggpubkey = CK_INVALID_HANDLE;
|
|
CK_ULONG signatlen = CK_IBM_BLS12_381_SIGN_LEN;
|
|
CK_BYTE aggsignature[1000];
|
|
CK_BYTE signature[CK_IBM_BLS_MAX_AGGREGATIONS][CK_IBM_BLS12_381_SIGN_LEN];
|
|
CK_ULONG aggsignaturelen = CK_IBM_BLS12_381_SIGN_LEN;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len, k, numElements = 10;
|
|
CK_FLAGS flags;
|
|
CK_RV rc;
|
|
CK_BYTE message[32];
|
|
CK_BBOOL lotrue = CK_TRUE;
|
|
CK_IBM_ECDSA_OTHER_PARAMS *param;
|
|
|
|
CK_ATTRIBUTE publicKeyTemplate[] = {
|
|
{ CKA_EC_PARAMS, (CK_BYTE *)bls_test.curve, bls_test.size },
|
|
{ CKA_VERIFY, &lotrue, sizeof(lotrue) },
|
|
{ CKA_DERIVE, &lotrue, sizeof(lotrue) },
|
|
};
|
|
CK_ULONG pub_derive_tmpl_len = sizeof(publicKeyTemplate)
|
|
/ sizeof(CK_ATTRIBUTE);
|
|
|
|
testsuite_begin("Starting run_BLSAggregation");
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if not EP11 token*/
|
|
if (!is_ep11_token(SLOT_ID)) {
|
|
testcase_skip("Slot %u doesn't support BLS aggregation",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (!mech_supported(SLOT_ID, bls_test_input.mech.mechanism)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
mech_to_str(bls_test_input.mech.mechanism));
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_EC_AGGREGATE)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
mech_to_str(CKM_IBM_EC_AGGREGATE));
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (k = 0; k < numElements; k++) {
|
|
|
|
testcase_new_assertion();
|
|
testcase_begin("Generate key pair with for index %lu", k);
|
|
|
|
rc = generate_EC_KeyPair(session, CKM_EC_KEY_PAIR_GEN,
|
|
(CK_BYTE *)bls_test.curve, bls_test.size,
|
|
&pub_key[k], &priv_key[k], !pkey);
|
|
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
goto testcase_cleanup;;
|
|
}
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, bls_test.name);
|
|
goto testcase_cleanup;;
|
|
}
|
|
testcase_fail("generate_EC_KeyPair with valid input failed (%s), "
|
|
"rc=%s", bls_test.name, p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_pass("*Generate supported key pair (%s) passed.",
|
|
bls_test.name);
|
|
|
|
blsparam1.pAggrElements[k] = (CK_OBJECT_HANDLE_PTR)&(pub_key[k]);
|
|
}
|
|
|
|
blsparam1.numElements = numElements;
|
|
blsparam1.elementSize = sizeof(CK_OBJECT_HANDLE_PTR);
|
|
blsparam2.numElements = numElements;
|
|
blsparam2.elementSize = CK_IBM_BLS12_381_SIGN_LEN;
|
|
|
|
for (k = 0; k < bls_test_input.inputlen; k++) {
|
|
message[k] = (k + 1) % 255;
|
|
}
|
|
|
|
for (k = 0; k < blsparam1.numElements; k++) {
|
|
testcase_new_assertion();
|
|
|
|
testcase_begin("Starting sign/verify with mechtype='%s', inputlen=%lu "
|
|
"parts=%lu, index=%lu",
|
|
p11_get_ckm(&mechtable_funcs,
|
|
bls_test_input.mech.mechanism),
|
|
bls_test_input.inputlen, bls_test_input.parts, k);
|
|
|
|
param = (CK_IBM_ECDSA_OTHER_PARAMS *)bls_test_input.mech.pParameter;
|
|
if (param->submechanism != CKM_IBM_BLS) {
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
/****** Sign *******/
|
|
rc = funcs->C_SignInit(session, &bls_test_input.mech, priv_key[k]);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Sign(session, message, bls_test_input.inputlen,
|
|
signature[k], &signatlen);
|
|
|
|
if (rc != 0) {
|
|
testcase_fail("C_Sign failed index=%lu.", k);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
/****** Verify *******/
|
|
rc = funcs->C_VerifyInit(session, &bls_test_input.mech,
|
|
*(CK_OBJECT_HANDLE_PTR)
|
|
blsparam1.pAggrElements[k]);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Verify(session, message, bls_test_input.inputlen,
|
|
signature[k], signatlen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_pass("*Sign & verify k=%lu, passed.", k);
|
|
|
|
blsparam2.pAggrElements[k] = (CK_BYTE_PTR)&(signature[k][0]);
|
|
}
|
|
|
|
mech.mechanism = CKM_IBM_EC_AGGREGATE;
|
|
mech.pParameter = &blsparam2;
|
|
mech.ulParameterLen = sizeof(blsparam2);
|
|
|
|
testcase_new_assertion();
|
|
|
|
testcase_begin("Starting BLS signature aggregation ");
|
|
rc = funcs->C_SignInit(session, &mech, CK_INVALID_HANDLE);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Sign(session, NULL, 0, NULL, &aggsignaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Sign(session, NULL,
|
|
0, aggsignature, &aggsignaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_pass("*BLS signature aggregation passed.");
|
|
|
|
testcase_new_assertion();
|
|
|
|
testcase_begin("Starting BLS public key aggregation ");
|
|
mech.mechanism = CKM_IBM_EC_AGGREGATE;
|
|
mech.pParameter = &blsparam1;
|
|
mech.ulParameterLen = sizeof(blsparam1);
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech, CK_INVALID_HANDLE,
|
|
publicKeyTemplate, pub_derive_tmpl_len,
|
|
&aggpubkey);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Derive rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_pass("*BLS Public key aggregation passed.");
|
|
|
|
testcase_new_assertion();
|
|
|
|
testcase_begin("Starting BLS aggregation verification");
|
|
|
|
rc = funcs->C_VerifyInit(session, &bls_test_input.mech, aggpubkey);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Verify(session, message, bls_test_input.inputlen,
|
|
&(aggsignature[0]), aggsignaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_pass("*Verification aggregation passed.");
|
|
|
|
testcase_cleanup:
|
|
|
|
for (k = 0; k < numElements; k++) {
|
|
if (pub_key[k] != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, pub_key[k]);
|
|
if (priv_key[k] != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key[k]);
|
|
}
|
|
|
|
if (aggpubkey != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, aggpubkey);
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
return rc;
|
|
}
|
|
|
|
static const struct {
|
|
CK_ULONG index;
|
|
CK_BYTE *key_info;
|
|
CK_ULONG key_info_len;
|
|
} eth_child_key_index[] = {
|
|
{ 0, NULL, 0 },
|
|
{ 0x12, (CK_BYTE *)"test", 4 },
|
|
{ 0x3456, (CK_BYTE *)"00112233445566778899", 20 },
|
|
{ 0x987654, NULL, 0 },
|
|
{ 0x7fffffff, NULL, 0 },
|
|
};
|
|
|
|
#define NUM_ETH_CHILD_KEY_INDEXES 5
|
|
|
|
/*
|
|
* Run Ethereum 2.0 Key Derivation tests:
|
|
* Derive a ETH master key from a generic secret key. Then derive child keys
|
|
* (public and private) from the master key.
|
|
*/
|
|
CK_RV run_DeriveETH(void)
|
|
{
|
|
CK_SESSION_HANDLE session;
|
|
CK_MECHANISM mech;
|
|
CK_FLAGS flags;
|
|
CK_OBJECT_HANDLE secret = CK_INVALID_HANDLE, master = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE child_priv = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE child_pub = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE child_pub2 = CK_INVALID_HANDLE;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len;
|
|
CK_RV rc = CKR_OK;
|
|
CK_BBOOL true = CK_TRUE;
|
|
CK_IBM_ETH_DERIVE_PARAMS eth_parms;
|
|
CK_OBJECT_CLASS priv_class = CKO_PRIVATE_KEY;
|
|
CK_OBJECT_CLASS pub_class = CKO_PUBLIC_KEY;
|
|
CK_KEY_TYPE key_type = CKK_EC;
|
|
CK_OBJECT_CLASS secret_class = CKO_SECRET_KEY;
|
|
CK_ULONG secret_keylen = 32;
|
|
CK_ULONG k;
|
|
|
|
CK_ATTRIBUTE secret_tmpl[] = {
|
|
{CKA_CLASS, &secret_class, sizeof(secret_class)},
|
|
{CKA_VALUE_LEN, &secret_keylen, sizeof(secret_keylen)},
|
|
{CKA_IBM_USE_AS_DATA, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG secret_tmpl_len = sizeof(secret_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE priv_derive_tmpl[] = {
|
|
{CKA_CLASS, &priv_class, sizeof(priv_class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_DERIVE, &true, sizeof(true)},
|
|
{CKA_EC_PARAMS, (CK_VOID_PTR)bls12_381, sizeof(bls12_381)},
|
|
{CKA_IBM_USE_AS_DATA, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG priv_derive_tmpl_len =
|
|
sizeof(priv_derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE pub_derive_tmpl[] = {
|
|
{CKA_CLASS, &pub_class, sizeof(pub_class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_DERIVE, &true, sizeof(true)},
|
|
{CKA_EC_PARAMS, (CK_VOID_PTR)bls12_381, sizeof(bls12_381)},
|
|
{CKA_IBM_USE_AS_DATA, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG pub_derive_tmpl_len =
|
|
sizeof(pub_derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
testsuite_begin("starting run_DeriveETH with pkey=%X ...", pkey);
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support "
|
|
"protected keys", (unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
if (!mech_supported(SLOT_ID, CKM_GENERIC_SECRET_KEY_GEN)) {
|
|
testcase_skip("Slot %u doesn't support CKM_GENERIC_SECRET_KEY_GEN\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
if (!mech_supported(SLOT_ID, CKM_IBM_ETH_DERIVE)) {
|
|
testcase_skip("Slot %u doesn't support CKM_IBM_ETH_DERIVE\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
/* Testcase #1: Derive the ETH master key from a secret key */
|
|
testcase_new_assertion();
|
|
testcase_begin("ETH master key derive with pkey=%X", pkey);
|
|
|
|
mech.mechanism = CKM_GENERIC_SECRET_KEY_GEN;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
rc = funcs->C_GenerateKey(session, &mech, secret_tmpl, secret_tmpl_len,
|
|
&secret);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_GenerateKey, rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
mech.mechanism = CKM_IBM_ETH_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_ETH_DERIVE_PARAMS);
|
|
mech.pParameter = ð_parms;
|
|
|
|
memset(ð_parms, 0, sizeof(eth_parms));
|
|
eth_parms.version = CK_IBM_ETH_DERIVE_PARAMS_VERSION_1;
|
|
eth_parms.sigVersion = CK_IBM_ETH_SIG_VERSION_4;
|
|
eth_parms.type = CK_IBM_ETH_EIP2333_MASTERK;
|
|
eth_parms.childKeyIndex = 0;
|
|
eth_parms.pKeyInfo = NULL;
|
|
eth_parms.ulKeyInfoLen = 0;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
secret, priv_derive_tmpl,
|
|
priv_derive_tmpl_len, &master);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey ETH master key: rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_pass("ETH master key derive with pkey=%X", pkey);
|
|
|
|
/* Derive child keys from the master key */
|
|
for (k = 0; k < NUM_ETH_CHILD_KEY_INDEXES; k++) {
|
|
/* Testcase #2: Derive private child key from private master key */
|
|
|
|
testcase_new_assertion();
|
|
testcase_begin("ETH priv-to-priv child key derive with "
|
|
"child-key-index=0x%lx, KeyInfoLen=%lu, pkey=%X",
|
|
eth_child_key_index[k].index,
|
|
eth_child_key_index[k].key_info_len, pkey);
|
|
|
|
mech.mechanism = CKM_IBM_ETH_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_ETH_DERIVE_PARAMS);
|
|
mech.pParameter = ð_parms;
|
|
|
|
eth_parms.version = CK_IBM_ETH_DERIVE_PARAMS_VERSION_1;
|
|
eth_parms.sigVersion = CK_IBM_ETH_SIG_VERSION_4;
|
|
eth_parms.type = CK_IBM_ETH_EIP2333_PRV2PRV;
|
|
eth_parms.childKeyIndex = eth_child_key_index[k].index;
|
|
eth_parms.pKeyInfo = eth_child_key_index[k].key_info;
|
|
eth_parms.ulKeyInfoLen = eth_child_key_index[k].key_info_len;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
master, priv_derive_tmpl,
|
|
priv_derive_tmpl_len, &child_priv);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey ETH child key (priv): rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto run_child_cleanup;
|
|
}
|
|
|
|
testcase_pass("ETH priv-to-priv child key derive with "
|
|
"child-key-index=0x%lx, KeyInfoLen=%lu, pkey=%X",
|
|
eth_child_key_index[k].index,
|
|
eth_child_key_index[k].key_info_len, pkey);
|
|
|
|
/* Testcase #3: Derive public child key from private master key */
|
|
testcase_new_assertion();
|
|
testcase_begin("ETH priv-to-pub child key derive with "
|
|
"child-key-index=0x%lx, KeyInfoLen=%lu, pkey=%X",
|
|
eth_child_key_index[k].index,
|
|
eth_child_key_index[k].key_info_len, pkey);
|
|
|
|
eth_parms.version = CK_IBM_ETH_DERIVE_PARAMS_VERSION_1;
|
|
eth_parms.sigVersion = CK_IBM_ETH_SIG_VERSION_4;
|
|
eth_parms.type = CK_IBM_ETH_EIP2333_PRV2PUB;
|
|
eth_parms.childKeyIndex = eth_child_key_index[k].index;
|
|
eth_parms.pKeyInfo = eth_child_key_index[k].key_info;
|
|
eth_parms.ulKeyInfoLen = eth_child_key_index[k].key_info_len;
|
|
|
|
mech.mechanism = CKM_IBM_ETH_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_ETH_DERIVE_PARAMS);
|
|
mech.pParameter = ð_parms;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
master, pub_derive_tmpl,
|
|
pub_derive_tmpl_len, &child_pub);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey ETH child key (pub): rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto run_child_cleanup;
|
|
}
|
|
|
|
testcase_pass("ETH priv-to-pub child key derive with "
|
|
"child-key-index=0x%lx, KeyInfoLen=%lu, pkey=%X",
|
|
eth_child_key_index[k].index,
|
|
eth_child_key_index[k].key_info_len, pkey);
|
|
|
|
/* Testcase #4: Test if derived keys are usable */
|
|
testcase_new_assertion();
|
|
|
|
mech.mechanism = CKM_ECDSA;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
rc = run_GenerateSignVerifyECC(session, &mech, 20, 0,
|
|
child_priv, child_pub,
|
|
CURVE_BLS12_381,
|
|
(CK_BYTE *)bls12_381,
|
|
sizeof(bls12_381));
|
|
if (rc != 0) {
|
|
testcase_fail("run_GenerateSignVerifyECC failed.");
|
|
goto run_child_cleanup;
|
|
}
|
|
testcase_pass("ETH check derived keys with child-key-index=0x%lx, "
|
|
"KeyInfoLen=%lu, pkey=%X", eth_child_key_index[k].index,
|
|
eth_child_key_index[k].key_info_len, pkey);
|
|
|
|
/*
|
|
* Testcase #5: Derive public child key from private key
|
|
*/
|
|
|
|
testcase_new_assertion();
|
|
testcase_begin("ETH priv-to-pub child key derive with "
|
|
"child-key-index=0x%lx, KeyInfoLen=%lu, pkey=%X",
|
|
eth_child_key_index[k].index,
|
|
eth_child_key_index[k].key_info_len, pkey);
|
|
|
|
mech.mechanism = CKM_IBM_ETH_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_IBM_ETH_DERIVE_PARAMS);
|
|
mech.pParameter = ð_parms;
|
|
|
|
eth_parms.version = CK_IBM_ETH_DERIVE_PARAMS_VERSION_1;
|
|
eth_parms.sigVersion = CK_IBM_ETH_SIG_VERSION_4;
|
|
eth_parms.type = CK_IBM_ETH_EIP2333_PRV2PUB;
|
|
eth_parms.childKeyIndex = eth_child_key_index[k].index;
|
|
eth_parms.pKeyInfo = eth_child_key_index[k].key_info;
|
|
eth_parms.ulKeyInfoLen = eth_child_key_index[k].key_info_len;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
child_priv, pub_derive_tmpl,
|
|
pub_derive_tmpl_len, &child_pub2);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey ETH child key (pub): rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto run_child_cleanup;
|
|
}
|
|
|
|
testcase_pass("ETH priv-to-pub child key derive with "
|
|
"child-key-index=0x%lx, KeyInfoLen=%lu, pkey=%X",
|
|
eth_child_key_index[k].index,
|
|
eth_child_key_index[k].key_info_len, pkey);
|
|
|
|
run_child_cleanup:
|
|
if (child_priv != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, child_priv);
|
|
child_priv = CK_INVALID_HANDLE;
|
|
if (child_pub != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, child_pub);
|
|
child_pub = CK_INVALID_HANDLE;
|
|
if (child_pub2 != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, child_pub2);
|
|
child_pub2 = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (secret != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret);
|
|
if (master != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, master);
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
#define NUMED 4
|
|
|
|
const _ec_struct der_ec_edwards_supported[NUMED] = {
|
|
{&curve25519, sizeof(curve25519), CK_FALSE, CURVE_MONTGOMERY,
|
|
CURVE256_LENGTH, "curve25519"},
|
|
{&curve448, sizeof(curve448), CK_FALSE, CURVE_MONTGOMERY,
|
|
CURVE448_LENGTH, "curve448"},
|
|
{&ed25519, sizeof(ed25519), CK_FALSE, CURVE_EDWARDS,
|
|
CURVE256_LENGTH, "ed25519"},
|
|
{&ed448, sizeof(ed448), CK_FALSE, CURVE_EDWARDS,
|
|
CURVE456_LENGTH, "ed448"},
|
|
};
|
|
|
|
CK_BYTE eddsa_ctx_data[] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
|
|
|
|
CK_EDDSA_PARAMS eddsa_none = { FALSE, 0, NULL };
|
|
CK_EDDSA_PARAMS eddsa_ph = { TRUE, 0, NULL };
|
|
CK_EDDSA_PARAMS eddsa_ctx = { FALSE, sizeof(eddsa_ctx_data), eddsa_ctx_data };
|
|
CK_EDDSA_PARAMS eddsa_ph_ctx = { TRUE, sizeof(eddsa_ctx_data), eddsa_ctx_data };
|
|
|
|
_signVerifyParam edwardsSignVerifyInput[] = {
|
|
{{CKM_EDDSA, NULL, 0}, 20, 0, ""},
|
|
{{CKM_EDDSA, NULL, 0}, 32, 0, ""},
|
|
{{CKM_EDDSA, NULL, 0}, 48, 0, ""},
|
|
{{CKM_EDDSA, NULL, 0}, 64, 0, ""},
|
|
{{CKM_EDDSA, &eddsa_none, sizeof(eddsa_none)}, 64, 0,
|
|
"Neither Pre-Hash nor Context"},
|
|
{{CKM_EDDSA, &eddsa_ph, sizeof(eddsa_ph)}, 64, 0, "Pre-Hash"},
|
|
{{CKM_EDDSA, &eddsa_ctx, sizeof(eddsa_ctx)}, 64, 0, "Context"},
|
|
{{CKM_EDDSA, &eddsa_ph_ctx, sizeof(eddsa_ph_ctx)}, 64, 0,
|
|
"Pre-Hash & Context"},
|
|
};
|
|
|
|
CK_RV run_GenerateEdwardsKeyPairSignVerify(void)
|
|
{
|
|
CK_MECHANISM mech;
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len, i = 0, j;
|
|
CK_FLAGS flags;
|
|
CK_MECHANISM_INFO mech_info;
|
|
CK_RV rc;
|
|
|
|
testcase_begin("Starting Edwards generate key pair with pkey=%X ...", pkey);
|
|
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support "
|
|
"protected keys", (unsigned int) SLOT_ID);
|
|
goto done;
|
|
}
|
|
|
|
mech.mechanism = CKM_EC_EDWARDS_KEY_PAIR_GEN;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
/* query the slot, check if this mech is supported */
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for EC key gen? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_EC_EDWARDS_KEY_PAIR_GEN",
|
|
(unsigned int) SLOT_ID);
|
|
rc = CKR_OK;
|
|
goto done;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < NUMED; i++) {
|
|
if (der_ec_edwards_supported[i].type != CURVE_EDWARDS)
|
|
continue;
|
|
|
|
rc = generate_EC_KeyPair(session, CKM_EC_EDWARDS_KEY_PAIR_GEN,
|
|
(CK_BYTE *)der_ec_edwards_supported[i].curve,
|
|
der_ec_edwards_supported[i].size,
|
|
&publ_key, &priv_key, !pkey);
|
|
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
der_ec_edwards_supported[i].name);
|
|
continue;
|
|
}
|
|
testcase_fail
|
|
("generate_EC_KeyPair with valid input failed at i=%lu (%s), "
|
|
"rc=%s", i, der_ec_edwards_supported[i].name, p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Generate supported key pair index=%lu (%s) passed.", i,
|
|
der_ec_edwards_supported[i].name);
|
|
|
|
for (j = 0;
|
|
j < (sizeof(edwardsSignVerifyInput) / sizeof(_signVerifyParam));
|
|
j++) {
|
|
|
|
if (memcmp(der_ec_edwards_supported[i].curve, ed448,
|
|
MIN(der_ec_edwards_supported[i].size,
|
|
sizeof(ed448))) == 0 &&
|
|
edwardsSignVerifyInput[j].mech.pParameter == NULL) {
|
|
/* Ed448 requires a mechanism parameter, skip */
|
|
continue;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
rc = run_GenerateSignVerifyECC(session,
|
|
&edwardsSignVerifyInput[j].mech,
|
|
edwardsSignVerifyInput[j].inputlen,
|
|
edwardsSignVerifyInput[j].parts,
|
|
priv_key, publ_key,
|
|
der_ec_edwards_supported[i].type,
|
|
(CK_BYTE *)der_ec_edwards_supported[i].curve,
|
|
der_ec_edwards_supported[i].size);
|
|
if (rc != 0) {
|
|
testcase_fail("run_GenerateSignVerifyECC failed index=%lu (%s).",
|
|
j, edwardsSignVerifyInput[j].name);
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_pass("*Sign & verify %s i=%lu (%s), j=%lu passed.",
|
|
edwardsSignVerifyInput[j].name, i,
|
|
der_ec_edwards_supported[i].name, j);
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
publ_key = CK_INVALID_HANDLE;
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
priv_key = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
rc = CKR_OK;
|
|
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
|
|
done:
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV run_ImportEdwardsKeyPairSignVerifyKAT(void)
|
|
{
|
|
CK_MECHANISM mech;
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len, i = 0, signaturelen;
|
|
CK_FLAGS flags;
|
|
CK_MECHANISM_INFO mech_info;
|
|
CK_EDDSA_PARAMS eddsa_param;
|
|
CK_BYTE signature[128];
|
|
CK_RV rc;
|
|
|
|
testcase_begin("Starting Edwards import key pair with pkey=%X ...", pkey);
|
|
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support "
|
|
"protected keys", (unsigned int) SLOT_ID);
|
|
goto done;
|
|
}
|
|
|
|
mech.mechanism = CKM_EDDSA;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
/* query the slot, check if this mech is supported */
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for EC key gen? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_EDDSA",
|
|
(unsigned int) SLOT_ID);
|
|
goto done;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ED_TV_NUM; i++) {
|
|
rc = create_ECPrivateKey(session, CKK_EC_EDWARDS,
|
|
ed_tv[i].params, ed_tv[i].params_len,
|
|
ed_tv[i].privkey, ed_tv[i].privkey_len,
|
|
&priv_key, !pkey, CK_FALSE);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC-Edwards key import is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ed_tv[i].name);
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC-Edwards Private Key) failed at "
|
|
"i=%lu (%s), rc=%s", i, ed_tv[i].name,
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Import EC-Edwards private key (%s) index=%lu passed.",
|
|
ed_tv[i].name, i);
|
|
|
|
rc = create_ECPublicKey(session, CKK_EC_EDWARDS,
|
|
ed_tv[i].params, ed_tv[i].params_len,
|
|
ed_tv[i].pubkey, ed_tv[i].pubkey_len,
|
|
&publ_key, !pkey);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC-Edwards key import is not allowed by policy");
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID, ed_tv[i].name);
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
continue;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC-Edwards Public Key) failed at "
|
|
"i=%lu (%s), rc=%s", i, ed_tv[i].name,
|
|
p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Import EC-Edwards public key (%s) index=%lu passed.",
|
|
ed_tv[i].name, i);
|
|
|
|
if (ed_tv[i].mech_param) {
|
|
eddsa_param.phFlag = ed_tv[i].prehash;
|
|
eddsa_param.pContextData = ed_tv[i].ctx;
|
|
eddsa_param.ulContextDataLen = ed_tv[i].ctx_len;
|
|
|
|
mech.pParameter = &eddsa_param;
|
|
mech.ulParameterLen = sizeof(eddsa_param);
|
|
} else {
|
|
mech.pParameter = NULL;
|
|
mech.ulParameterLen = 0;
|
|
}
|
|
|
|
/* create signature with private key */
|
|
rc = funcs->C_SignInit(session, &mech, priv_key);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID) {
|
|
testcase_skip("EdDSA mechanism parameter combination is not "
|
|
"supported (%s)", ed_tv[i].name);
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
memset(signature, 0, sizeof(signature));
|
|
|
|
signaturelen = sizeof(signature);
|
|
rc = funcs->C_Sign(session, ed_tv[i].msg, ed_tv[i].msg_len,
|
|
signature, &signaturelen);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID) {
|
|
testcase_skip("EdDSA mechanism parameter combination is not "
|
|
"supported (%s)", ed_tv[i].name);
|
|
rc = CKR_OK;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
/* Verify signature with public key */
|
|
rc = funcs->C_VerifyInit(session, &mech, publ_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_Verify(session, ed_tv[i].msg, ed_tv[i].msg_len,
|
|
signature, signaturelen);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (signaturelen != ed_tv[i].signature_len ||
|
|
memcmp(signature, ed_tv[i].signature, signaturelen) != 0) {
|
|
testcase_fail("Signature is not the expected one at "
|
|
"i=%lu (%s)", i, ed_tv[i].name);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
testcase_pass("*Sign & Verify with expected result (%s) index=%lu passed.",
|
|
ed_tv[i].name, i);
|
|
|
|
// clean up
|
|
testcase_cleanup:
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
publ_key = CK_INVALID_HANDLE;
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
priv_key = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
|
|
done:
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV run_TransferEdwardsMontgomeryKeyPair(void)
|
|
{
|
|
CK_MECHANISM mech;
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
CK_SESSION_HANDLE session;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len, i = 0;
|
|
CK_FLAGS flags;
|
|
CK_MECHANISM_INFO mech_info;
|
|
CK_RV rc;
|
|
CK_MECHANISM aes_keygen_mech;
|
|
CK_OBJECT_HANDLE secret_key = CK_INVALID_HANDLE;
|
|
CK_BYTE_PTR wrapped_key = NULL;
|
|
CK_ULONG wrapped_keylen;
|
|
CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE;
|
|
CK_MECHANISM wrap_mech;
|
|
|
|
testcase_begin("Starting Edwards/Montgomery transfer key pair with "
|
|
"pkey=%X ...", pkey);
|
|
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support "
|
|
"protected keys", (unsigned int) SLOT_ID);
|
|
goto done;
|
|
}
|
|
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_KEY_GEN, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for AES key gen? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_AES_KEY_GEN",
|
|
(unsigned int) SLOT_ID);
|
|
goto done;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_CBC_PAD, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for AES CBC wrap? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD",
|
|
(unsigned int) SLOT_ID);
|
|
goto done;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto done;
|
|
}
|
|
}
|
|
if ((mech_info.flags & CKF_WRAP) == 0 ||
|
|
(mech_info.flags & CKF_UNWRAP) == 0) {
|
|
/* no support for AES CBC wrap? skip */
|
|
testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD for wrapping "
|
|
"keys", (unsigned int) SLOT_ID);
|
|
goto done;
|
|
}
|
|
|
|
for (i = 0; i < NUMED; i++) {
|
|
if (der_ec_edwards_supported[i].type == CURVE_EDWARDS)
|
|
mech.mechanism = CKM_EC_EDWARDS_KEY_PAIR_GEN;
|
|
else if (der_ec_edwards_supported[i].type == CURVE_MONTGOMERY)
|
|
mech.mechanism = CKM_EC_MONTGOMERY_KEY_PAIR_GEN;
|
|
else
|
|
continue;
|
|
|
|
/* query the slot, check if this mech is supported */
|
|
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_MECHANISM_INVALID) {
|
|
/* no support for EC key gen? skip */
|
|
testcase_skip("Slot %u doesn't support %s",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism));
|
|
goto testcase_cleanup;
|
|
} else {
|
|
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
}
|
|
|
|
rc = generate_EC_KeyPair(session, mech.mechanism,
|
|
(CK_BYTE *)der_ec_edwards_supported[i].curve,
|
|
der_ec_edwards_supported[i].size,
|
|
&publ_key, &priv_key, !pkey);
|
|
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
der_ec_edwards_supported[i].name);
|
|
continue;
|
|
}
|
|
testcase_fail
|
|
("generate_EC_KeyPair with valid input failed at i=%lu (%s), "
|
|
"rc=%s", i, der_ec_edwards_supported[i].name, p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_pass("*Generate supported key pair index=%lu (%s) passed.", i,
|
|
der_ec_edwards_supported[i].name);
|
|
|
|
/* create wrapping key (secret key) */
|
|
aes_keygen_mech.mechanism = CKM_AES_KEY_GEN;
|
|
|
|
CK_OBJECT_CLASS wkclass = CKO_SECRET_KEY;
|
|
CK_ULONG keylen = 32;
|
|
CK_BBOOL true = TRUE;
|
|
CK_BBOOL false = FALSE;
|
|
CK_BBOOL sign = TRUE;
|
|
CK_BBOOL derive = TRUE;
|
|
CK_BYTE wrap_key_label[] = "Wrap_Key";
|
|
CK_OBJECT_CLASS wclass = CKO_PRIVATE_KEY;
|
|
CK_KEY_TYPE keyType = (mech.mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN ?
|
|
CKK_EC_EDWARDS : CKK_EC_MONTGOMERY);
|
|
CK_ATTRIBUTE cka_wrap_tmpl[] = {
|
|
{CKA_PRIVATE, &true, sizeof(true)},
|
|
{CKA_CLASS, &wclass, sizeof(wclass)},
|
|
{CKA_KEY_TYPE, &keyType, sizeof(keyType)},
|
|
};
|
|
CK_ATTRIBUTE cka_unwrap_tmpl[] = {
|
|
{CKA_DECRYPT, &true, sizeof(true)},
|
|
{CKA_SIGN, &sign, sizeof(sign)},
|
|
{CKA_DERIVE, &derive, sizeof(derive)},
|
|
{CKA_PRIVATE, &true, sizeof(true)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &true, sizeof(true)},
|
|
{CKA_EXTRACTABLE, &false, sizeof(false)},
|
|
};
|
|
CK_ATTRIBUTE secret_tmpl[] = {
|
|
{CKA_CLASS, &wkclass, sizeof(wkclass)},
|
|
{CKA_VALUE_LEN, &keylen, sizeof(keylen)},
|
|
{CKA_LABEL, &wrap_key_label, sizeof(wrap_key_label)},
|
|
{CKA_TOKEN, &true, sizeof(true)},
|
|
{CKA_WRAP, &true, sizeof(true)},
|
|
{CKA_UNWRAP, &true, sizeof(true)},
|
|
{CKA_WRAP_TEMPLATE, &cka_wrap_tmpl, sizeof(cka_wrap_tmpl)},
|
|
{CKA_UNWRAP_TEMPLATE, &cka_unwrap_tmpl, sizeof(cka_unwrap_tmpl)},
|
|
};
|
|
CK_ULONG secret_tmpl_len = sizeof(secret_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
if (der_ec_edwards_supported[i].type == CURVE_EDWARDS)
|
|
derive = FALSE;
|
|
if (der_ec_edwards_supported[i].type == CURVE_MONTGOMERY)
|
|
sign = FALSE;
|
|
|
|
if (is_icsf_token(SLOT_ID))
|
|
secret_tmpl_len -= 2; /* ICSF does not support array-attributes */
|
|
|
|
rc = funcs->C_GenerateKey(session, &aes_keygen_mech, secret_tmpl,
|
|
secret_tmpl_len, &secret_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GenerateKey, rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
/* wrap/unwrap private and public Edwards key with a transport key */
|
|
wrap_mech.mechanism = CKM_AES_CBC_PAD;
|
|
wrap_mech.pParameter = "0123456789abcdef";
|
|
wrap_mech.ulParameterLen = 16;
|
|
rc = funcs->C_WrapKey(session, &wrap_mech, secret_key, priv_key,
|
|
NULL, &wrapped_keylen);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_KEY_NOT_WRAPPABLE) {
|
|
testcase_skip("Slot %u doesn't support this to wrap keys of "
|
|
"type 0x%lx", (unsigned int) SLOT_ID, keyType);
|
|
} else {
|
|
testcase_error("C_WrapKey(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
wrapped_key = calloc(wrapped_keylen, sizeof(CK_BYTE));
|
|
if (wrapped_key == NULL) {
|
|
testcase_error("Can't allocate memory for %lu bytes.",
|
|
sizeof(CK_BYTE) * wrapped_keylen);
|
|
rc = CKR_HOST_MEMORY;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_WrapKey(session, &wrap_mech, secret_key, priv_key,
|
|
wrapped_key, &wrapped_keylen);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_KEY_NOT_WRAPPABLE) {
|
|
testcase_skip("Slot %u doesn't support this to wrap keys of "
|
|
"type 0x%lx", (unsigned int) SLOT_ID, keyType);
|
|
} else {
|
|
testcase_error("C_WrapKey(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
|
|
CK_KEY_TYPE key_type = (mech.mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN ?
|
|
CKK_EC_EDWARDS : CKK_EC_MONTGOMERY);
|
|
CK_BYTE unwrap_label[] = "unwrapped_private_EC_Key";
|
|
CK_BYTE id[] = { 123 };
|
|
|
|
CK_ATTRIBUTE unwrap_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_TOKEN, &true, sizeof(true)},
|
|
{CKA_LABEL, &unwrap_label, sizeof(unwrap_label)},
|
|
{CKA_ID, id, sizeof(id)},
|
|
{CKA_SENSITIVE, &true, sizeof(true)},
|
|
{CKA_DERIVE, &derive, sizeof(derive)},
|
|
{CKA_SIGN, &sign, sizeof(sign)},
|
|
{CKA_EXTRACTABLE, &false, sizeof(false)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &true, sizeof(true)},
|
|
};
|
|
CK_ULONG unwrap_tmpl_len = sizeof(unwrap_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE unwrap_base_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
{CKA_DERIVE, &derive, sizeof(derive)},
|
|
{CKA_SIGN, &sign, sizeof(sign)},
|
|
};
|
|
|
|
if (is_icsf_token(SLOT_ID))
|
|
unwrap_tmpl_len -= 1; /* ICSF does not supp. CKA_IBM_PROTKEY_... */
|
|
|
|
rc = funcs->C_UnwrapKey(session, &wrap_mech, secret_key,
|
|
wrapped_key, wrapped_keylen,
|
|
unwrap_tmpl, unwrap_tmpl_len,
|
|
&unwrapped_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_UnwrapKey, rc=%s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
// unwrap again with each CKA_SENSITIVE / CKA_EXTRACTABLE choice; the
|
|
// transport key's CKA_UNWRAP_TEMPLATE sets CKA_EXTRACTABLE = FALSE
|
|
// (except on ICSF, which gets no array attributes)
|
|
rc = check_unwrap_sensitive_extractable(session, &wrap_mech,
|
|
secret_key, wrapped_key, wrapped_keylen, unwrap_base_tmpl,
|
|
sizeof(unwrap_base_tmpl) / sizeof(CK_ATTRIBUTE),
|
|
CKA_VALUE, NULL,
|
|
is_icsf_token(SLOT_ID) ? NULL : &false);
|
|
if (rc != CKR_OK)
|
|
goto testcase_cleanup;
|
|
|
|
if (wrapped_key) {
|
|
free(wrapped_key);
|
|
wrapped_key = NULL;
|
|
}
|
|
|
|
if (mech.mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) {
|
|
/*
|
|
* create signature with unwrapped private key and verify with
|
|
* public key
|
|
*/
|
|
testcase_new_assertion();
|
|
|
|
rc = run_GenerateSignVerifyECC(session,
|
|
&edwardsSignVerifyInput[0].mech,
|
|
edwardsSignVerifyInput[0].inputlen,
|
|
edwardsSignVerifyInput[0].parts,
|
|
unwrapped_key, publ_key,
|
|
der_ec_edwards_supported[i].type,
|
|
(CK_BYTE *)der_ec_edwards_supported[i].curve,
|
|
der_ec_edwards_supported[i].size);
|
|
if (rc != 0) {
|
|
testcase_fail("run_GenerateSignVerifyECC failed index=0 (%s).",
|
|
edwardsSignVerifyInput[0].name);
|
|
goto testcase_cleanup;
|
|
}
|
|
testcase_pass("*Sign & verify %s i=%lu (%s), passed.",
|
|
edwardsSignVerifyInput[0].name, i,
|
|
der_ec_edwards_supported[i].name);
|
|
} else {
|
|
CK_OBJECT_HANDLE secret_key = CK_INVALID_HANDLE;
|
|
CK_ECDH1_DERIVE_PARAMS ecdh_parm;
|
|
CK_BYTE ec_point[64];
|
|
CK_ATTRIBUTE ec_point_attr =
|
|
{ CKA_EC_POINT, ec_point, sizeof(ec_point) };
|
|
CK_BBOOL extractable = !pkey;
|
|
CK_KEY_TYPE secret_key_type = CKK_GENERIC_SECRET;
|
|
CK_ULONG secret_key_len =
|
|
(der_ec_edwards_supported[i].bit_len + 7) / 8;
|
|
CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY;
|
|
CK_ATTRIBUTE derive_tmpl[] = {
|
|
{CKA_CLASS, &secret_key_class, sizeof(secret_key_class)},
|
|
{CKA_KEY_TYPE, &secret_key_type, sizeof(secret_key_type)},
|
|
{CKA_VALUE_LEN, &secret_key_len, sizeof(secret_key_len)},
|
|
{CKA_SENSITIVE, &false, sizeof(false)},
|
|
{CKA_EXTRACTABLE, &extractable, sizeof(CK_BBOOL)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &pkey, sizeof(CK_BBOOL)},
|
|
};
|
|
CK_ULONG derive_tmpl_len = sizeof(derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
testcase_new_assertion();
|
|
|
|
/* Perform ECDH with unwrapped private key and public key */
|
|
rc = funcs->C_GetAttributeValue(session, publ_key,
|
|
&ec_point_attr, 1);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_GetAttributeValue: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
ecdh_parm.kdf = CKD_NULL;
|
|
ecdh_parm.pPublicData = ec_point_attr.pValue;
|
|
ecdh_parm.ulPublicDataLen = ec_point_attr.ulValueLen;
|
|
ecdh_parm.pSharedData = NULL;
|
|
ecdh_parm.ulSharedDataLen = 0;
|
|
|
|
mech.mechanism = CKM_ECDH1_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parm;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
unwrapped_key, derive_tmpl,
|
|
derive_tmpl_len, &secret_key);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
der_ec_edwards_supported[i].name);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
testcase_fail("C_DeriveKey: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs->C_DestroyObject(session, secret_key);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
}
|
|
|
|
testcase_pass("*ECDH i=%lu (%s), passed.", i,
|
|
der_ec_edwards_supported[i].name);
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
publ_key = CK_INVALID_HANDLE;
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
priv_key = CK_INVALID_HANDLE;
|
|
if (secret_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_key);
|
|
secret_key = CK_INVALID_HANDLE;
|
|
if (unwrapped_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, unwrapped_key);
|
|
unwrapped_key = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
if (secret_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_key);
|
|
if (unwrapped_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, unwrapped_key);
|
|
|
|
if (wrapped_key)
|
|
free(wrapped_key);
|
|
|
|
done:
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV run_MontgomeryECDHKeyKAT(void)
|
|
{
|
|
CK_SESSION_HANDLE session;
|
|
CK_MECHANISM mech;
|
|
CK_FLAGS flags;
|
|
CK_OBJECT_HANDLE publ_keyA = CK_INVALID_HANDLE,
|
|
priv_keyA = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE publ_keyB = CK_INVALID_HANDLE,
|
|
priv_keyB = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE secret_keyA = CK_INVALID_HANDLE,
|
|
secret_keyB = CK_INVALID_HANDLE;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_KEY_TYPE secret_key_type = CKK_GENERIC_SECRET;
|
|
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
|
|
CK_ECDH1_DERIVE_PARAMS ecdh_parmA, ecdh_parmB;
|
|
CK_BBOOL false = CK_FALSE;
|
|
CK_ULONG user_pin_len;
|
|
CK_RV rc = CKR_OK;
|
|
CK_BYTE secretA_value[1000] = { 0 }; // enough space for key lengths in ecdh_tv[]
|
|
CK_BYTE secretB_value[1000] = { 0 };
|
|
CK_BYTE mac1[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac1_len = sizeof(mac1);
|
|
CK_BYTE mac2[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac2_len = sizeof(mac2);
|
|
CK_BYTE macexpected[SHA1_HASH_SIZE] = { 0 };
|
|
CK_ULONG macexpected_len = sizeof(macexpected);
|
|
CK_ULONG i;
|
|
|
|
testcase_begin("starting run_MontgomeryECDHKeyKAT with pkey=%X ...", pkey);
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support "
|
|
"protected keys",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (!mech_supported(SLOT_ID, CKM_EC_MONTGOMERY_KEY_PAIR_GEN)) {
|
|
testcase_skip("Slot %u doesn't support CKM_EC_MONTGOMERY_KEY_PAIR_GEN\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (!mech_supported(SLOT_ID, CKM_ECDH1_DERIVE)) {
|
|
testcase_skip("Slot %u doesn't support CKM_ECDH1_DERIVE\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if ((is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) &&
|
|
!mech_supported(SLOT_ID, CKM_SHA_1_HMAC)) {
|
|
testcase_skip("Slot %u doesn't support CKM_SHA_1_HMAC, correctness "
|
|
"of derived keys can not be verified\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
if (is_cca_token(SLOT_ID)) {
|
|
testcase_skip("The CCA token in slot %u doesn't support ECDH with EC "
|
|
"keys imported from clear, only with randomly generated "
|
|
"keys. KATs not possible because of that\n",
|
|
(unsigned int) SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (i=0; i< MONTGOMERY_ECDH_TV_NUM; i++) {
|
|
|
|
testcase_begin("Starting with shared secret i=%lu (%s), pkey=%X",
|
|
i, montgomery_ecdh_tv[i].name, pkey);
|
|
|
|
if ((is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) &&
|
|
!check_supp_keysize(SLOT_ID, CKM_SHA_1_HMAC,
|
|
montgomery_ecdh_tv[i].derived_key_len * 8)) {
|
|
testcase_skip("Mechanism CKM_SHA_1_HMAC can not be used with "
|
|
"keys of size %lu. Correctness of derived key "
|
|
"can not be verified.",
|
|
montgomery_ecdh_tv[i].derived_key_len);
|
|
continue;
|
|
}
|
|
|
|
// First, import the EC-Montgomery key pair for party A
|
|
rc = create_ECPrivateKey(session, CKK_EC_MONTGOMERY,
|
|
montgomery_ecdh_tv[i].params,
|
|
montgomery_ecdh_tv[i].params_len,
|
|
montgomery_ecdh_tv[i].privkeyA,
|
|
montgomery_ecdh_tv[i].privkey_len,
|
|
&priv_keyA, !pkey, CK_TRUE);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
montgomery_ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = create_ECPublicKey(session, CKK_EC_MONTGOMERY,
|
|
montgomery_ecdh_tv[i].params,
|
|
montgomery_ecdh_tv[i].params_len,
|
|
montgomery_ecdh_tv[i].pubkeyA,
|
|
montgomery_ecdh_tv[i].pubkey_len,
|
|
&publ_keyA, !pkey);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_POLICY_VIOLATION) {
|
|
testcase_skip("EC key import is not allowed by policy");
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
continue;
|
|
}
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
montgomery_ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Now import the EC key pair for party B
|
|
rc = create_ECPrivateKey(session, CKK_EC_MONTGOMERY,
|
|
montgomery_ecdh_tv[i].params,
|
|
montgomery_ecdh_tv[i].params_len,
|
|
montgomery_ecdh_tv[i].privkeyB,
|
|
montgomery_ecdh_tv[i].privkey_len,
|
|
&priv_keyB, !pkey, CK_TRUE);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
montgomery_ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = create_ECPublicKey(session, CKK_EC_MONTGOMERY,
|
|
montgomery_ecdh_tv[i].params,
|
|
montgomery_ecdh_tv[i].params_len,
|
|
montgomery_ecdh_tv[i].pubkeyB,
|
|
montgomery_ecdh_tv[i].pubkey_len,
|
|
&publ_keyB, !pkey);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
montgomery_ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, "
|
|
"rc=%s", i, p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Now derive the secrets...
|
|
|
|
CK_ATTRIBUTE secretA_tmpl[] = {
|
|
{CKA_VALUE, secretA_value, sizeof(secretA_value)}
|
|
};
|
|
CK_ULONG secretA_tmpl_len = sizeof(secretA_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_ATTRIBUTE secretB_tmpl[] = {
|
|
{CKA_VALUE, secretB_value, sizeof(secretB_value)}
|
|
};
|
|
CK_ULONG secretB_tmpl_len = sizeof(secretB_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_BBOOL extractable = !pkey;
|
|
CK_ATTRIBUTE derive_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE, &secret_key_type, sizeof(secret_key_type)},
|
|
{CKA_VALUE_LEN, &(montgomery_ecdh_tv[i].derived_key_len), sizeof(CK_ULONG)},
|
|
{CKA_SENSITIVE, &false, sizeof(false)},
|
|
{CKA_EXTRACTABLE, &extractable, sizeof(CK_BBOOL)},
|
|
{CKA_IBM_PROTKEY_EXTRACTABLE, &pkey, sizeof(CK_BBOOL)},
|
|
};
|
|
CK_ULONG derive_tmpl_len = sizeof(derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
// Now, derive a generic secret key using party A's private key
|
|
// and B's public key
|
|
ecdh_parmA.kdf = montgomery_ecdh_tv[i].kdf;
|
|
ecdh_parmA.pPublicData = montgomery_ecdh_tv[i].pubkeyB;
|
|
ecdh_parmA.ulPublicDataLen = montgomery_ecdh_tv[i].pubkey_len;
|
|
ecdh_parmA.pSharedData = NULL;
|
|
ecdh_parmA.ulSharedDataLen = 0;
|
|
|
|
mech.mechanism = CKM_ECDH1_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parmA;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
priv_keyA, derive_tmpl,
|
|
derive_tmpl_len, &secret_keyA);
|
|
if (rc != CKR_OK) {
|
|
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
montgomery_ecdh_tv[i].name);
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_fail("C_DeriveKey #1: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Now, derive a generic secret key using B's private key and
|
|
// A's public key
|
|
ecdh_parmB.kdf = montgomery_ecdh_tv[i].kdf;
|
|
ecdh_parmB.pPublicData = montgomery_ecdh_tv[i].pubkeyA;
|
|
ecdh_parmB.ulPublicDataLen = montgomery_ecdh_tv[i].pubkey_len;
|
|
ecdh_parmB.pSharedData = NULL;
|
|
ecdh_parmB.ulSharedDataLen = 0;
|
|
|
|
mech.mechanism = CKM_ECDH1_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parmB;
|
|
|
|
rc = funcs->C_DeriveKey(session, &mech,
|
|
priv_keyB, derive_tmpl,
|
|
derive_tmpl_len, &secret_keyB);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("C_DeriveKey #2: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
|
|
/* A secure key token won't reveal the key value in clear */
|
|
if (!is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
// Extract the derived secret A
|
|
rc = funcs->C_GetAttributeValue(session, secret_keyA,
|
|
secretA_tmpl, secretA_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #3:rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare lengths of derived secret from key object
|
|
if (montgomery_ecdh_tv[i].derived_key_len !=
|
|
secretA_tmpl[0].ulValueLen) {
|
|
testcase_fail("ERROR: derived key #1 length = %lu, "
|
|
"derived key #2 length = %lu",
|
|
montgomery_ecdh_tv[i].derived_key_len,
|
|
secretA_tmpl[0].ulValueLen);
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare with known value
|
|
if (memcmp(secretA_tmpl[0].pValue,
|
|
montgomery_ecdh_tv[i].derived_key,
|
|
montgomery_ecdh_tv[i].derived_key_len) != 0) {
|
|
testcase_fail("ERROR: derived key mismatch, i=%lu",i);
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Extract the derived secret B
|
|
rc = funcs->C_GetAttributeValue(session, secret_keyB,
|
|
secretB_tmpl, secretB_tmpl_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_error("C_GetAttributeValue #4:rc = %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare lengths of derived secret from key object
|
|
if (montgomery_ecdh_tv[i].derived_key_len !=
|
|
secretB_tmpl[0].ulValueLen) {
|
|
testcase_fail("ERROR: derived key #1 length = %lu, "
|
|
"derived key #2 length = %lu",
|
|
montgomery_ecdh_tv[i].derived_key_len,
|
|
secretB_tmpl[0].ulValueLen);
|
|
goto testcase_next;
|
|
}
|
|
|
|
// Compare with known value
|
|
if (memcmp(secretB_tmpl[0].pValue,
|
|
montgomery_ecdh_tv[i].derived_key,
|
|
montgomery_ecdh_tv[i].derived_key_len) != 0) {
|
|
testcase_fail("ERROR: derived key mismatch, i=%lu",i);
|
|
goto testcase_next;
|
|
}
|
|
} else {
|
|
/* Secure key:
|
|
* Calculate HMAC with derived keys and expected key and compare
|
|
* the MAC.
|
|
*/
|
|
rc = run_HMACSign_OpenSSL(montgomery_ecdh_tv[i].derived_key,
|
|
montgomery_ecdh_tv[i].derived_key_len,
|
|
CKM_SHA_1_HMAC,
|
|
macexpected, &macexpected_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("HMAC for expected key failed: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = run_HMACSign(session, secret_keyA,
|
|
montgomery_ecdh_tv[i].derived_key_len,
|
|
CKM_SHA_1_HMAC, mac1, &mac1_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("HMAC for derived key #1 failed: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
if (mac1_len != 0 && /* skip check if mac can't be calculated */
|
|
(mac1_len != macexpected_len ||
|
|
memcmp(mac1, macexpected, mac1_len) != 0)) {
|
|
testcase_fail("ERROR: derived key #1 does not produce the "
|
|
"expected HMAC");
|
|
goto testcase_next;
|
|
}
|
|
|
|
rc = run_HMACSign(session, secret_keyB,
|
|
montgomery_ecdh_tv[i].derived_key_len,
|
|
CKM_SHA_1_HMAC, mac2, &mac2_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("HMAC for derived key #2 failed: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
if (mac2_len != 0 && /* skip check if mac can't be calculated */
|
|
(mac2_len != macexpected_len ||
|
|
memcmp(mac2, macexpected, mac2_len) != 0)) {
|
|
testcase_fail("ERROR: derived key #2 does not produce the "
|
|
"expected HMAC");
|
|
goto testcase_next;
|
|
}
|
|
}
|
|
|
|
testcase_pass("*Derive shared secret i=%lu (%s) passed.", i,
|
|
montgomery_ecdh_tv[i].name);
|
|
|
|
testcase_next:
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
priv_keyA = CK_INVALID_HANDLE;
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
publ_keyA = CK_INVALID_HANDLE;
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
priv_keyB = CK_INVALID_HANDLE;
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
publ_keyB = CK_INVALID_HANDLE;
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
secret_keyA = CK_INVALID_HANDLE;
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
secret_keyB = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (priv_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyA);
|
|
if (publ_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyA);
|
|
if (priv_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_keyB);
|
|
if (publ_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_keyB);
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
typedef struct ecdh_encaps_decaps_params {
|
|
_ec_struct curve;
|
|
CK_KEY_TYPE sym_key_type;
|
|
CK_ULONG sym_key_size;
|
|
CK_EC_KDF_TYPE kdf;
|
|
CK_BYTE *shared_data;
|
|
CK_ULONG shared_data_len;
|
|
} ecdh_encaps_decaps_params;
|
|
|
|
const ecdh_encaps_decaps_params ecdh_encaps_decaps_tests[] = {
|
|
{ .curve = { &prime256v1, sizeof(prime256v1), CK_FALSE,
|
|
CURVE_PRIME, CURVE256_LENGTH, "prime256v1" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_NULL,
|
|
.shared_data = NULL,
|
|
.shared_data_len = 0,
|
|
},
|
|
{ .curve = { &prime256v1, sizeof(prime256v1), CK_FALSE,
|
|
CURVE_PRIME, CURVE256_LENGTH, "prime256v1" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &secp521r1, sizeof(secp521r1), CK_FALSE,
|
|
CURVE_PRIME, CURVE521_LENGTH + 8, "secp521r1" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &brainpoolP256r1, sizeof(brainpoolP256r1), CK_FALSE,
|
|
CURVE_BRAINPOOL, CURVE256_LENGTH, "brainpoolP256r1" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &brainpoolP512r1, sizeof(brainpoolP512r1), CK_FALSE,
|
|
CURVE_BRAINPOOL, CURVE512_LENGTH, "brainpoolP512r1" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &curve25519, sizeof(curve25519), CK_FALSE,
|
|
CURVE_MONTGOMERY, CURVE256_LENGTH, "curve25519" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &curve448, sizeof(curve448), CK_FALSE,
|
|
CURVE_MONTGOMERY, CURVE448_LENGTH, "curve448" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &prime256v1, sizeof(prime256v1), CK_FALSE,
|
|
CURVE_PRIME, CURVE256_LENGTH, "prime256v1" },
|
|
.sym_key_type = CKK_AES,
|
|
.sym_key_size = 16,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &prime256v1, sizeof(prime256v1), CK_FALSE,
|
|
CURVE_PRIME, CURVE256_LENGTH, "prime256v1" },
|
|
.sym_key_type = CKK_AES_XTS,
|
|
.sym_key_size = 64,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &prime256v1, sizeof(prime256v1), CK_FALSE,
|
|
CURVE_PRIME, CURVE256_LENGTH, "prime256v1" },
|
|
.sym_key_type = CKK_GENERIC_SECRET,
|
|
.sym_key_size = 32,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
{ .curve = { &prime256v1, sizeof(prime256v1), CK_FALSE,
|
|
CURVE_PRIME, CURVE256_LENGTH, "prime256v1" },
|
|
.sym_key_type = CKK_GENERIC_SECRET,
|
|
.sym_key_size = 64,
|
|
.kdf = CKD_SHA256_KDF,
|
|
.shared_data = (CK_BYTE *)"abcdefg",
|
|
.shared_data_len = 6,
|
|
},
|
|
};
|
|
|
|
#define NUMENCAPSDECAPS sizeof(ecdh_encaps_decaps_tests) / \
|
|
sizeof(ecdh_encaps_decaps_params)
|
|
|
|
CK_RV run_EncapsDecapsECDH(CK_BBOOL cofactor_mode)
|
|
{
|
|
CK_SESSION_HANDLE session;
|
|
CK_MECHANISM mech;
|
|
CK_FLAGS flags;
|
|
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE,
|
|
priv_key = CK_INVALID_HANDLE;
|
|
CK_OBJECT_HANDLE secret_keyA = CK_INVALID_HANDLE,
|
|
secret_keyB = CK_INVALID_HANDLE;
|
|
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
CK_ULONG user_pin_len;
|
|
CK_RV rc = CKR_OK;
|
|
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
|
|
CK_ECDH1_DERIVE_PARAMS ecdh_parm;
|
|
CK_ULONG i;
|
|
CK_BBOOL ck_true = CK_TRUE;
|
|
CK_BBOOL ck_false = CK_FALSE;
|
|
CK_BYTE *cipher = NULL;
|
|
CK_ULONG cipher_len;
|
|
CK_BYTE mac1[SHA256_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac1_len = sizeof(mac1);
|
|
CK_BYTE mac2[SHA256_HASH_SIZE] = { 0 };
|
|
CK_ULONG mac2_len = sizeof(mac2);
|
|
CK_BYTE enc1[AES_BLOCK_SIZE] = { 0 };
|
|
CK_ULONG enc1_len = sizeof(enc1);
|
|
CK_BYTE enc2[AES_BLOCK_SIZE] = { 0 };
|
|
CK_ULONG enc2_len = sizeof(enc2);
|
|
|
|
testcase_begin("starting run_EncapsDecapsECDH %s with pkey=%X ...",
|
|
cofactor_mode ? "in cofactor mode" : "", pkey);
|
|
testcase_rw_session();
|
|
testcase_user_login();
|
|
|
|
/* Skip tests if pkey = true, but the slot doesn't support protected keys*/
|
|
if (pkey && !is_ep11_token(SLOT_ID) && !is_cca_token(SLOT_ID)) {
|
|
testcase_skip("pkey test option is true, but slot %u doesn't support "
|
|
"protected keys", (unsigned int)SLOT_ID);
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
mech.mechanism = cofactor_mode ?
|
|
CKM_ECDH1_COFACTOR_DERIVE : CKM_ECDH1_DERIVE;
|
|
if (!mech_supported(SLOT_ID, mech.mechanism)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int)SLOT_ID,
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism));
|
|
goto testcase_cleanup;
|
|
}
|
|
if (!encapsulate_supported(SLOT_ID, mech) ||
|
|
!decapsulate_supported(SLOT_ID, mech)) {
|
|
testcase_skip("Slot %u doesn't support key encapsulation with %s",
|
|
(unsigned int)SLOT_ID,
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism));
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
for (i = 0; i < NUMENCAPSDECAPS; i++) {
|
|
CK_ATTRIBUTE decaps_tmp[] = {
|
|
{CKA_KEY_TYPE,
|
|
(CK_VOID_PTR)&ecdh_encaps_decaps_tests[i].sym_key_type,
|
|
sizeof(ecdh_encaps_decaps_tests[i].sym_key_type)},
|
|
{CKA_VALUE_LEN,
|
|
(CK_VOID_PTR)&ecdh_encaps_decaps_tests[i].sym_key_size,
|
|
sizeof(ecdh_encaps_decaps_tests[i].sym_key_size)},
|
|
};
|
|
CK_ATTRIBUTE prv_attr[] = {
|
|
{CKA_SIGN, &ck_true, sizeof(ck_true)},
|
|
{CKA_EXTRACTABLE, &ck_true, sizeof(ck_true)},
|
|
{CKA_SENSITIVE, &ck_true, sizeof(ck_true)},
|
|
{CKA_DERIVE, &ck_false, sizeof(ck_false)},
|
|
{CKA_DECAPSULATE, &ck_true, sizeof(ck_true)},
|
|
{CKA_DECAPSULATE_TEMPLATE, &decaps_tmp, sizeof(decaps_tmp)},
|
|
};
|
|
CK_ULONG prv_attr_len = sizeof(prv_attr)/sizeof(CK_ATTRIBUTE);
|
|
CK_ATTRIBUTE pub_attr[] = {
|
|
{CKA_EC_PARAMS,
|
|
(CK_VOID_PTR)ecdh_encaps_decaps_tests[i].curve.curve,
|
|
ecdh_encaps_decaps_tests[i].curve.size},
|
|
{CKA_VERIFY, &ck_true, sizeof(ck_true)},
|
|
{CKA_DERIVE, &ck_false, sizeof(ck_false)},
|
|
{CKA_ENCAPSULATE, &ck_true, sizeof(ck_true)},
|
|
};
|
|
CK_ULONG pub_attr_len = sizeof(pub_attr)/sizeof(CK_ATTRIBUTE);
|
|
|
|
CK_ATTRIBUTE encaps_decaps_tmpl[] = {
|
|
{CKA_CLASS, &class, sizeof(class)},
|
|
{CKA_KEY_TYPE,
|
|
(CK_VOID_PTR)&ecdh_encaps_decaps_tests[i].sym_key_type,
|
|
sizeof(ecdh_encaps_decaps_tests[i].sym_key_type)},
|
|
{CKA_EXTRACTABLE, &ck_false, sizeof(ck_false)},
|
|
{CKA_SENSITIVE, &ck_true, sizeof(ck_true)},
|
|
{CKA_VALUE_LEN,
|
|
(CK_VOID_PTR)&ecdh_encaps_decaps_tests[i].sym_key_size,
|
|
sizeof(ecdh_encaps_decaps_tests[i].sym_key_size)},
|
|
};
|
|
CK_ULONG encaps_decaps_tmpl_len =
|
|
sizeof(encaps_decaps_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
|
|
mech.mechanism = cofactor_mode ?
|
|
CKM_ECDH1_COFACTOR_DERIVE : CKM_ECDH1_DERIVE;
|
|
|
|
testcase_begin("Starting with mech=%s, index=%lu, curve=%s, kdf=%s, "
|
|
"keytype=0x%lx, keylen=%lu, shared_data=%lu, pkey=%X",
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism), i,
|
|
ecdh_encaps_decaps_tests[i].curve.name,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf),
|
|
ecdh_encaps_decaps_tests[i].sym_key_type,
|
|
ecdh_encaps_decaps_tests[i].sym_key_size,
|
|
ecdh_encaps_decaps_tests[i].shared_data_len,
|
|
pkey);
|
|
|
|
/* Check the curve */
|
|
if (ecdh_encaps_decaps_tests[i].curve.type == CURVE_EDWARDS||
|
|
ecdh_encaps_decaps_tests[i].curve.type == CURVE_BLS12_381) {
|
|
/* Edwards/BLS curves can not be used for ECDH encaps/decaps */
|
|
continue;
|
|
}
|
|
|
|
if (is_cca_token(SLOT_ID)) {
|
|
if (ecdh_encaps_decaps_tests[i].curve.twisted) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
ecdh_encaps_decaps_tests[i].curve.name);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Check the KDF */
|
|
switch (ecdh_encaps_decaps_tests[i].kdf) {
|
|
case CKD_SHA1_KDF:
|
|
case CKD_SHA1_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA_1)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA224_KDF:
|
|
case CKD_SHA224_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA224)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA256_KDF:
|
|
case CKD_SHA256_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA256)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA384_KDF:
|
|
case CKD_SHA384_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA384)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA512_KDF:
|
|
case CKD_SHA512_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA512)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_224_KDF:
|
|
case CKD_SHA3_224_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_224)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));;
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_256_KDF:
|
|
case CKD_SHA3_256_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_256)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_384_KDF:
|
|
case CKD_SHA3_384_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_384)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
case CKD_SHA3_512_KDF:
|
|
case CKD_SHA3_512_KDF_SP800:
|
|
if (!mech_supported(SLOT_ID, CKM_SHA3_512)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int) SLOT_ID,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (is_cca_token(SLOT_ID)) {
|
|
switch (ecdh_encaps_decaps_tests[i].kdf) {
|
|
case CKD_SHA224_KDF:
|
|
case CKD_SHA256_KDF:
|
|
case CKD_SHA384_KDF:
|
|
case CKD_SHA512_KDF:
|
|
break;
|
|
default:
|
|
testcase_skip("CCA token can not en/decapsulate keys with "
|
|
"this KDF %s",
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Check the to be en/decapsulated key type and size */
|
|
if (is_cca_token(SLOT_ID)) {
|
|
if (ecdh_encaps_decaps_tests[i].sym_key_type != CKK_AES) {
|
|
testcase_skip("CCA token can not en/decapsulate keys other "
|
|
"than AES\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Generate the EC key pair for party A */
|
|
mech.mechanism =
|
|
ecdh_encaps_decaps_tests[i].curve.type == CURVE_MONTGOMERY ?
|
|
CKM_EC_MONTGOMERY_KEY_PAIR_GEN : CKM_EC_KEY_PAIR_GEN;
|
|
mech.ulParameterLen = 0;
|
|
mech.pParameter = NULL;
|
|
|
|
if (!mech_supported(SLOT_ID, mech.mechanism)) {
|
|
testcase_skip("Slot %u doesn't support %s\n",
|
|
(unsigned int)SLOT_ID,
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism));
|
|
continue;
|
|
}
|
|
|
|
rc = funcs->C_GenerateKeyPair(session, &mech,
|
|
pub_attr, pub_attr_len,
|
|
prv_attr, prv_attr_len,
|
|
&publ_key, &priv_key);
|
|
if (rc != CKR_OK) {
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("EC key generation is not allowed by policy");
|
|
goto testcase_next;
|
|
}
|
|
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
(unsigned int) SLOT_ID,
|
|
ecdh_encaps_decaps_tests[i].curve.name);
|
|
goto testcase_next;
|
|
}
|
|
testcase_new_assertion();
|
|
testcase_fail("C_GenerateKeyPair with valid input failed at i=%lu "
|
|
"(%s), rc=%s", i,
|
|
ecdh_encaps_decaps_tests[i].curve.name,
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
/* Encapsulate on party B */
|
|
mech.mechanism = cofactor_mode ?
|
|
CKM_ECDH1_COFACTOR_DERIVE : CKM_ECDH1_DERIVE;
|
|
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
mech.pParameter = &ecdh_parm;
|
|
|
|
ecdh_parm.kdf = ecdh_encaps_decaps_tests[i].kdf;
|
|
ecdh_parm.pSharedData = ecdh_encaps_decaps_tests[i].shared_data;
|
|
ecdh_parm.ulSharedDataLen = ecdh_encaps_decaps_tests[i].shared_data_len;
|
|
ecdh_parm.pPublicData = NULL;
|
|
ecdh_parm.ulPublicDataLen = 0;
|
|
|
|
rc = funcs3_2->C_EncapsulateKey(session, &mech, publ_key,
|
|
encaps_decaps_tmpl,
|
|
encaps_decaps_tmpl_len,
|
|
NULL, &cipher_len, NULL);
|
|
if (rc != CKR_OK) {
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
(ecdh_parm.kdf != CKD_NULL ||
|
|
ecdh_parm.ulSharedDataLen > 0)) {
|
|
testcase_skip("EP11 does not support KDF %s and/or "
|
|
"shared data with older firmware "
|
|
"versions\n",
|
|
p11_get_ckd(ecdh_parm.kdf));
|
|
goto testcase_next;
|
|
}
|
|
if (rc == CKR_KEY_TYPE_INCONSISTENT) {
|
|
testcase_skip("Slot %u doesn't support to en/decaps key "
|
|
"type 0x%lx", (unsigned int) SLOT_ID,
|
|
ecdh_encaps_decaps_tests[i].sym_key_type);
|
|
goto testcase_next;
|
|
}
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("key derivation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_FUNCTION_CANCELED) {
|
|
testcase_skip("key derivation is not allowed by "
|
|
"adapter control point");
|
|
goto testcase_next;
|
|
}
|
|
if (rc == CKR_KEY_SIZE_RANGE) {
|
|
testcase_skip("key derivation is not allowed because key to be "
|
|
"generated is stronger than the input material.");
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
testcase_fail("C_EncapsulateKey #1: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
cipher = calloc(cipher_len, sizeof(CK_BYTE));
|
|
if (cipher == NULL) {
|
|
testcase_error("Can't allocate memory for %lu bytes.", cipher_len);
|
|
rc = CKR_HOST_MEMORY;
|
|
goto testcase_cleanup;
|
|
}
|
|
|
|
rc = funcs3_2->C_EncapsulateKey(session, &mech, publ_key,
|
|
encaps_decaps_tmpl,
|
|
encaps_decaps_tmpl_len,
|
|
cipher, &cipher_len, &secret_keyB);
|
|
if (rc != CKR_OK) {
|
|
if (is_ep11_token(SLOT_ID) &&
|
|
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
(ecdh_parm.kdf != CKD_NULL ||
|
|
ecdh_parm.ulSharedDataLen > 0)) {
|
|
testcase_skip("EP11 does not support KDF %s and/or "
|
|
"shared data with older firmware "
|
|
"versions\n",
|
|
p11_get_ckd(ecdh_parm.kdf));
|
|
goto testcase_next;
|
|
}
|
|
if (rc == CKR_KEY_TYPE_INCONSISTENT) {
|
|
testcase_skip("Slot %u doesn't support to en/decaps key "
|
|
"type 0x%lx", (unsigned int) SLOT_ID,
|
|
ecdh_encaps_decaps_tests[i].sym_key_type);
|
|
goto testcase_next;
|
|
}
|
|
if (is_rejected_by_policy(rc, session)) {
|
|
testcase_skip("key derivation is not allowed by policy");
|
|
continue;
|
|
}
|
|
if (rc == CKR_FUNCTION_CANCELED) {
|
|
testcase_skip("key derivation is not allowed by "
|
|
"adapter control point");
|
|
goto testcase_next;
|
|
}
|
|
if (rc == CKR_KEY_SIZE_RANGE) {
|
|
testcase_skip("key derivation is not allowed because key to be "
|
|
"generated is stronger than the input material.");
|
|
goto testcase_next;
|
|
}
|
|
|
|
testcase_new_assertion();
|
|
testcase_fail("C_EncapsulateKey #2: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
/* Decapsulate on party A */
|
|
rc = funcs3_2->C_DecapsulateKey(session, &mech, priv_key,
|
|
encaps_decaps_tmpl,
|
|
encaps_decaps_tmpl_len,
|
|
cipher, cipher_len, &secret_keyA);
|
|
if (rc != CKR_OK) {
|
|
testcase_new_assertion();
|
|
testcase_fail("C_DecapsulateKey: rc = %s", p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
/* Check if encapsulated key is the same as the decapsukated key */
|
|
testcase_new_assertion();
|
|
switch (ecdh_encaps_decaps_tests[i].sym_key_type) {
|
|
case CKK_GENERIC_SECRET:
|
|
mac1_len = sizeof(mac1);
|
|
rc = run_HMACSign(session, secret_keyB,
|
|
ecdh_encaps_decaps_tests[i].sym_key_size,
|
|
CKM_SHA256_HMAC, mac1, &mac1_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Encapsulated key #1 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
mac2_len = sizeof(mac2);
|
|
rc = run_HMACSign(session, secret_keyA,
|
|
ecdh_encaps_decaps_tests[i].sym_key_size,
|
|
CKM_SHA256_HMAC, mac2, &mac2_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Decapsulated key #2 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
if (mac1_len != mac2_len ||
|
|
memcmp(mac1, mac2, mac1_len) != 0) {
|
|
testcase_fail("ERROR: en/Decapsulated keys do not produce the "
|
|
"same HMAC");
|
|
goto testcase_next;
|
|
}
|
|
break;
|
|
|
|
case CKK_AES:
|
|
enc1_len = sizeof(enc1);
|
|
rc = run_AESEncrypt(session, secret_keyB, enc1, &enc1_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Encapsulated key #1 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
enc2_len = sizeof(enc2);
|
|
rc = run_AESEncrypt(session, secret_keyA, enc2, &enc2_len);
|
|
if (rc != CKR_OK) {
|
|
testcase_fail("Decapsulated key #2 is not usable: %s",
|
|
p11_get_ckr(rc));
|
|
goto testcase_next;
|
|
}
|
|
|
|
if (enc1_len != enc2_len ||
|
|
memcmp(enc1, enc2, enc1_len) != 0) {
|
|
testcase_fail("ERROR: en/decapsulated keys do not produce the "
|
|
"same encrypted cipher text");
|
|
goto testcase_next;
|
|
}
|
|
break;
|
|
}
|
|
|
|
testcase_pass("EnDecapsulate shared secret mech=%s, index=%lu, "
|
|
"curve=%s, kdf=%s, keytype=ox%lx, keylen=%lu, "
|
|
"shared_data=%lu passed.",
|
|
p11_get_ckm(&mechtable_funcs, mech.mechanism), i,
|
|
ecdh_encaps_decaps_tests[i].curve.name,
|
|
p11_get_ckd(ecdh_encaps_decaps_tests[i].kdf),
|
|
ecdh_encaps_decaps_tests[i].sym_key_type,
|
|
ecdh_encaps_decaps_tests[i].sym_key_size,
|
|
ecdh_encaps_decaps_tests[i].shared_data_len);
|
|
|
|
testcase_next:
|
|
if (cipher)
|
|
free(cipher);
|
|
cipher = NULL;
|
|
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
secret_keyA = CK_INVALID_HANDLE;
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
secret_keyB = CK_INVALID_HANDLE;
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
publ_key = CK_INVALID_HANDLE;
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
priv_key = CK_INVALID_HANDLE;
|
|
}
|
|
|
|
testcase_cleanup:
|
|
if (cipher)
|
|
free(cipher);
|
|
|
|
if (secret_keyA != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyA);
|
|
secret_keyA = CK_INVALID_HANDLE;
|
|
if (secret_keyB != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, secret_keyB);
|
|
secret_keyB = CK_INVALID_HANDLE;
|
|
if (publ_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, publ_key);
|
|
publ_key = CK_INVALID_HANDLE;
|
|
if (priv_key != CK_INVALID_HANDLE)
|
|
funcs->C_DestroyObject(session, priv_key);
|
|
priv_key = CK_INVALID_HANDLE;
|
|
|
|
testcase_user_logout();
|
|
testcase_close_session();
|
|
|
|
return rc;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
CK_C_INITIALIZE_ARGS cinit_args;
|
|
int rc;
|
|
CK_RV rv;
|
|
|
|
rc = do_ParseArgs(argc, argv);
|
|
if (rc != 1)
|
|
return rc;
|
|
|
|
printf("Using slot #%lu...\n\n", SLOT_ID);
|
|
printf("With options: combined_extract: %d, nostop: %d\n",
|
|
combined_extract, no_stop);
|
|
if (combined_extract)
|
|
printf("\n--------------------------------------------------------\n"
|
|
"Caution: combined_extract does only work on systems with\n"
|
|
"control point 75 (XCP_CPB_ALLOW_COMBINED_EXTRACT)='on'.\n"
|
|
"--------------------------------------------------------\n\n");
|
|
|
|
rc = do_GetFunctionList();
|
|
if (!rc) {
|
|
PRINT_ERR("ERROR do_GetFunctionList() Failed , rc = 0x%0x\n", rc);
|
|
return rc;
|
|
}
|
|
|
|
memset(&cinit_args, 0x0, sizeof(cinit_args));
|
|
cinit_args.flags = CKF_OS_LOCKING_OK;
|
|
|
|
// SAB Add calls to ALL functions before the C_Initialize gets hit
|
|
|
|
funcs->C_Initialize(&cinit_args);
|
|
|
|
{
|
|
CK_SESSION_HANDLE hsess = 0;
|
|
|
|
rc = funcs->C_GetFunctionStatus(hsess);
|
|
if (rc != CKR_FUNCTION_NOT_PARALLEL)
|
|
return rc;
|
|
|
|
rc = funcs->C_CancelFunction(hsess);
|
|
if (rc != CKR_FUNCTION_NOT_PARALLEL)
|
|
return rc;
|
|
}
|
|
|
|
testcase_setup();
|
|
|
|
pkey = CK_FALSE;
|
|
rv = run_GenerateECCKeyPairSignVerify();
|
|
rv += run_ImportECCKeyPairSignVerify();
|
|
rv += run_TransferECCKeyPairSignVerify();
|
|
rv += run_DeriveECDHKey(FALSE);
|
|
rv += run_DeriveECDHKey(TRUE);
|
|
rv += run_DeriveECDHKeyKAT();
|
|
rv += run_DeriveBTC();
|
|
rv += run_BLSAggregation();
|
|
rv += run_DeriveETH();
|
|
rv += run_GenerateEdwardsKeyPairSignVerify();
|
|
rv += run_ImportEdwardsKeyPairSignVerifyKAT();
|
|
rv += run_TransferEdwardsMontgomeryKeyPair();
|
|
rv += run_MontgomeryECDHKeyKAT();
|
|
rv += run_EncapsDecapsECDH(FALSE);
|
|
rv += run_EncapsDecapsECDH(TRUE);
|
|
|
|
#ifndef NO_PKEY
|
|
if (is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) {
|
|
pkey = CK_TRUE;
|
|
rv += run_GenerateECCKeyPairSignVerify();
|
|
rv += run_ImportECCKeyPairSignVerify();
|
|
rv += run_TransferECCKeyPairSignVerify();
|
|
rv += run_DeriveECDHKey(FALSE);
|
|
rv += run_DeriveECDHKeyKAT();
|
|
rv += run_ImportSignVerify_Pkey();
|
|
rv += run_GenerateEdwardsKeyPairSignVerify();
|
|
rv += run_ImportEdwardsKeyPairSignVerifyKAT();
|
|
rv += run_TransferEdwardsMontgomeryKeyPair();
|
|
rv += run_MontgomeryECDHKeyKAT();
|
|
rv += run_EncapsDecapsECDH(FALSE);
|
|
}
|
|
#endif
|
|
|
|
testcase_print_result();
|
|
|
|
funcs->C_Finalize(NULL);
|
|
|
|
return testcase_return(rv);
|
|
}
|