|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* COPYRIGHT (c) International Business Machines Corp. 2011-2017
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* This program is provided under the terms of the Common Public License,
|
|
Packit |
8681c6 |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit |
8681c6 |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit |
8681c6 |
* found in the file LICENSE file or at
|
|
Packit |
8681c6 |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include <windows.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include <stdio.h>
|
|
Packit |
8681c6 |
#include <stdlib.h>
|
|
Packit |
8681c6 |
#include <string.h>
|
|
Packit |
8681c6 |
#include <memory.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include "pkcs11types.h"
|
|
Packit |
8681c6 |
#include "regress.h"
|
|
Packit |
8681c6 |
#include "common.c"
|
|
Packit |
8681c6 |
#include "ec.h"
|
|
Packit |
8681c6 |
#include "defs.h"
|
|
Packit |
8681c6 |
#include "ec_curves.h"
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* Below is a list for the OIDs and DER encodings of the brainpool.
|
|
Packit |
8681c6 |
* Beginning of each DER encoding should be 06 for OID and 09 for the length.
|
|
Packit |
8681c6 |
* For example brainpoolP160r1 should be 06092B2403030208010101
|
|
Packit |
8681c6 |
* brainpoolP160r1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.1
|
|
Packit |
8681c6 |
* 2B2403030208010101
|
|
Packit |
8681c6 |
* brainpoolP160t1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.2
|
|
Packit |
8681c6 |
* 2B2403030208010102
|
|
Packit |
8681c6 |
* brainpoolP192r1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.3
|
|
Packit |
8681c6 |
* 2B2403030208010103
|
|
Packit |
8681c6 |
* brainpoolP192t1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.4
|
|
Packit |
8681c6 |
* 2B2403030208010104
|
|
Packit |
8681c6 |
* brainpoolP224r1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.5
|
|
Packit |
8681c6 |
* 2B2403030208010105
|
|
Packit |
8681c6 |
* brainpoolP224t1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.6
|
|
Packit |
8681c6 |
* 2B2403030208010106
|
|
Packit |
8681c6 |
* brainpoolP256r1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.7
|
|
Packit |
8681c6 |
* 2B2403030208010107
|
|
Packit |
8681c6 |
* brainpoolP256t1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.8
|
|
Packit |
8681c6 |
* 2B2403030208010108
|
|
Packit |
8681c6 |
* brainpoolP320r1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.9
|
|
Packit |
8681c6 |
* 2B2403030208010109
|
|
Packit |
8681c6 |
* brainpoolP320t1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.10
|
|
Packit |
8681c6 |
* 2B240303020801010A
|
|
Packit |
8681c6 |
* brainpoolP384r1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.11
|
|
Packit |
8681c6 |
* 2B240303020801010B
|
|
Packit |
8681c6 |
* brainpoolP384t1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.12
|
|
Packit |
8681c6 |
* 2B240303020801010C
|
|
Packit |
8681c6 |
* brainpoolP512r1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.13
|
|
Packit |
8681c6 |
* 2B240303020801010D
|
|
Packit |
8681c6 |
* brainpoolP512t1
|
|
Packit |
8681c6 |
* 1.3.36.3.3.2.8.1.1.14
|
|
Packit |
8681c6 |
* 2B240303020801010E
|
|
Packit |
8681c6 |
* prime192
|
|
Packit |
8681c6 |
* 1.2.840.10045.3.1.1
|
|
Packit |
8681c6 |
* 2A8648CE3D030101
|
|
Packit |
8681c6 |
* secp224
|
|
Packit |
8681c6 |
* 1.3.132.0.33
|
|
Packit |
8681c6 |
* 2B81040021
|
|
Packit |
8681c6 |
* prime256
|
|
Packit |
8681c6 |
* 1.2.840.10045.3.1.7
|
|
Packit |
8681c6 |
* 2A8648CE3D030107
|
|
Packit |
8681c6 |
* secp384
|
|
Packit |
8681c6 |
* 1.3.132.0.34
|
|
Packit |
8681c6 |
* 2B81040022
|
|
Packit |
8681c6 |
* secp521
|
|
Packit |
8681c6 |
* 1.3.132.0.35
|
|
Packit |
8681c6 |
* 2B81040023
|
|
Packit |
8681c6 |
* secp256k1
|
|
Packit |
8681c6 |
* 1.3.132.0.10
|
|
Packit |
8681c6 |
* 2B8104000A
|
|
Packit |
8681c6 |
* curve25519
|
|
Packit |
8681c6 |
* 1.3.101.110
|
|
Packit |
8681c6 |
* 06032B656E
|
|
Packit |
8681c6 |
* curve448[]
|
|
Packit |
8681c6 |
* 1.3.101.111
|
|
Packit |
8681c6 |
* 06032B656F
|
|
Packit |
8681c6 |
* ed25519[]
|
|
Packit |
8681c6 |
* 1.3.101.112
|
|
Packit |
8681c6 |
* 06032B6570
|
|
Packit |
8681c6 |
* ed448
|
|
Packit |
8681c6 |
* 1.3.101.113
|
|
Packit |
8681c6 |
* 06032B6571
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ULONG total_assertions = 65;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
typedef struct ec_struct {
|
|
Packit |
8681c6 |
void const *curve;
|
|
Packit |
8681c6 |
CK_ULONG size;
|
|
Packit |
8681c6 |
CK_BBOOL twisted;
|
|
Packit |
8681c6 |
enum curve_type type;
|
|
Packit |
8681c6 |
CK_ULONG bit_len;
|
|
Packit |
8681c6 |
char *name;
|
|
Packit |
8681c6 |
} _ec_struct;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Supported Elliptic Curves */
|
|
Packit |
8681c6 |
#define NUMEC 24
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP160r1[] = OCK_BRAINPOOL_P160R1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP160t1[] = OCK_BRAINPOOL_P160T1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP192r1[] = OCK_BRAINPOOL_P192R1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP192t1[] = OCK_BRAINPOOL_P192T1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP224r1[] = OCK_BRAINPOOL_P224R1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP224t1[] = OCK_BRAINPOOL_P224T1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP256r1[] = OCK_BRAINPOOL_P256R1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP256t1[] = OCK_BRAINPOOL_P256T1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP320r1[] = OCK_BRAINPOOL_P320R1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP320t1[] = OCK_BRAINPOOL_P320T1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP384r1[] = OCK_BRAINPOOL_P384R1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP384t1[] = OCK_BRAINPOOL_P384T1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP512r1[] = OCK_BRAINPOOL_P512R1;
|
|
Packit |
8681c6 |
const CK_BYTE brainpoolP512t1[] = OCK_BRAINPOOL_P512T1;
|
|
Packit |
8681c6 |
const CK_BYTE prime192v1[] = OCK_PRIME192V1;
|
|
Packit |
8681c6 |
const CK_BYTE secp224r1[] = OCK_SECP224R1;
|
|
Packit |
8681c6 |
const CK_BYTE prime256v1[] = OCK_PRIME256V1;
|
|
Packit |
8681c6 |
const CK_BYTE secp384r1[] = OCK_SECP384R1;
|
|
Packit |
8681c6 |
const CK_BYTE secp521r1[] = OCK_SECP521R1;
|
|
Packit |
8681c6 |
const CK_BYTE secp256k1[] = OCK_SECP256K1;
|
|
Packit |
8681c6 |
const CK_BYTE curve25519[] = OCK_CURVE25519;
|
|
Packit |
8681c6 |
const CK_BYTE curve448[] = OCK_CURVE448;
|
|
Packit |
8681c6 |
const CK_BYTE ed25519[] = OCK_ED25519;
|
|
Packit |
8681c6 |
const CK_BYTE ed448[] = OCK_ED448;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
const _ec_struct der_ec_supported[NUMEC] = {
|
|
Packit |
8681c6 |
{&brainpoolP160r1, sizeof(brainpoolP160r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE160_LENGTH, "brainpoolP160r1"},
|
|
Packit |
8681c6 |
{&brainpoolP160t1, sizeof(brainpoolP160t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE160_LENGTH, "brainpoolP160t1"},
|
|
Packit |
8681c6 |
{&brainpoolP192r1, sizeof(brainpoolP192r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE192_LENGTH, "brainpoolP192r1"},
|
|
Packit |
8681c6 |
{&brainpoolP192t1, sizeof(brainpoolP192t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE192_LENGTH, "brainpoolP192t1"},
|
|
Packit |
8681c6 |
{&brainpoolP224r1, sizeof(brainpoolP224r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE224_LENGTH, "brainpoolP224r1"},
|
|
Packit |
8681c6 |
{&brainpoolP224t1, sizeof(brainpoolP224t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE224_LENGTH, "brainpoolP224t1"},
|
|
Packit |
8681c6 |
{&brainpoolP256r1, sizeof(brainpoolP256r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "brainpoolP256r1"},
|
|
Packit |
8681c6 |
{&brainpoolP256t1, sizeof(brainpoolP256t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "brainpoolP256t1"},
|
|
Packit |
8681c6 |
{&brainpoolP320r1, sizeof(brainpoolP320r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE320_LENGTH, "brainpoolP320r1"},
|
|
Packit |
8681c6 |
{&brainpoolP320t1, sizeof(brainpoolP320t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE320_LENGTH, "brainpoolP320t1"},
|
|
Packit |
8681c6 |
{&brainpoolP384r1, sizeof(brainpoolP384r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE384_LENGTH, "brainpoolP384r1"},
|
|
Packit |
8681c6 |
{&brainpoolP384t1, sizeof(brainpoolP384t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE384_LENGTH, "brainpoolP384t1"},
|
|
Packit |
8681c6 |
{&brainpoolP512r1, sizeof(brainpoolP512r1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE512_LENGTH, "brainpoolP512r1"},
|
|
Packit |
8681c6 |
{&brainpoolP512t1, sizeof(brainpoolP512t1), CK_TRUE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE512_LENGTH, "brainpoolP512t1"},
|
|
Packit |
8681c6 |
{&prime192v1, sizeof(prime192v1), CK_FALSE, CURVE_PRIME,
|
|
Packit |
8681c6 |
CURVE192_LENGTH, "prime192v1"},
|
|
Packit |
8681c6 |
{&secp224r1, sizeof(secp224r1), CK_FALSE, CURVE_PRIME,
|
|
Packit |
8681c6 |
CURVE224_LENGTH , "secp224r1"},
|
|
Packit |
8681c6 |
{&prime256v1, sizeof(prime256v1), CK_FALSE, CURVE_PRIME,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "prime256v1"},
|
|
Packit |
8681c6 |
{&secp384r1, sizeof(secp384r1), CK_FALSE, CURVE_PRIME,
|
|
Packit |
8681c6 |
CURVE384_LENGTH, "secp384r1"},
|
|
Packit |
8681c6 |
{&secp521r1, sizeof(secp521r1), CK_FALSE, CURVE_PRIME,
|
|
Packit |
8681c6 |
CURVE521_LENGTH + 8, "secp521r1"},
|
|
Packit |
8681c6 |
{&secp256k1, sizeof(secp256k1), CK_FALSE, CURVE_PRIME,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "secp256k1"},
|
|
Packit |
8681c6 |
{&curve25519, sizeof(curve25519), CK_FALSE, CURVE_MONTGOMERY,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "curve25519"},
|
|
Packit |
8681c6 |
{&curve448, sizeof(curve448), CK_FALSE, CURVE_MONTGOMERY,
|
|
Packit |
8681c6 |
CURVE456_LENGTH, "curve448"},
|
|
Packit |
8681c6 |
{&ed25519, sizeof(ed25519), CK_FALSE, CURVE_EDWARDS,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "ed25519"},
|
|
Packit |
8681c6 |
{&ed448, sizeof(ed448), CK_FALSE, CURVE_EDWARDS,
|
|
Packit |
8681c6 |
CURVE456_LENGTH, "ed448"},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Invalid curves */
|
|
Packit |
8681c6 |
#define NUMECINVAL 4
|
|
Packit |
8681c6 |
const CK_BYTE invalidCurve[] =
|
|
Packit |
8681c6 |
{ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x08, 0x08, 0x01, 0x01, 0x01 };
|
|
Packit |
8681c6 |
const CK_BYTE invalidLen1[] =
|
|
Packit |
8681c6 |
{ 0x06, 0x0A, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01 };
|
|
Packit |
8681c6 |
const CK_BYTE invalidLen2[] =
|
|
Packit |
8681c6 |
{ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01 };
|
|
Packit |
8681c6 |
const CK_BYTE invalidOIDfield[] =
|
|
Packit |
8681c6 |
{ 0x05, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01 };
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
const _ec_struct der_ec_notsupported[NUMECINVAL] = {
|
|
Packit |
8681c6 |
{&invalidCurve, sizeof(invalidCurve), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "invalidCurve"},
|
|
Packit |
8681c6 |
{&invalidLen1, sizeof(invalidLen1), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "invalidLen1"},
|
|
Packit |
8681c6 |
{&invalidLen2, sizeof(invalidLen2), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "invalidLen2"},
|
|
Packit |
8681c6 |
{&invalidOIDfield, sizeof(invalidOIDfield), CK_FALSE, CURVE_BRAINPOOL,
|
|
Packit |
8681c6 |
CURVE256_LENGTH, "invalidOIDfield"}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
typedef struct signVerifyParam {
|
|
Packit |
8681c6 |
CK_MECHANISM_TYPE mechtype;
|
|
Packit |
8681c6 |
CK_ULONG inputlen;
|
|
Packit |
8681c6 |
CK_ULONG parts; /* 0 means process in 1 chunk via C_Sign,
|
|
Packit |
8681c6 |
* >0 means process in n chunks via
|
|
Packit |
8681c6 |
* C_SignUpdate/C_SignFinal
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
} _signVerifyParam;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
_signVerifyParam signVerifyInput[] = {
|
|
Packit |
8681c6 |
{CKM_ECDSA, 20, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA, 32, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA, 48, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA, 64, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA1, 100, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA1, 100, 4},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA224, 100, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA224, 100, 4},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA256, 100, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA256, 100, 4},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA384, 100, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA384, 100, 4},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA512, 100, 0},
|
|
Packit |
8681c6 |
{CKM_ECDSA_SHA512, 100, 4},
|
|
Packit Service |
8aa27d |
{CKM_IBM_ED25519_SHA512, 100, 0},
|
|
Packit |
8681c6 |
{CKM_IBM_ED448_SHA3, 100, 0},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#define NUM_KDFS sizeof(kdfs)/sizeof(CK_EC_KDF_TYPE)
|
|
Packit |
8681c6 |
static CK_EC_KDF_TYPE kdfs[] = {
|
|
Packit |
8681c6 |
CKD_NULL,
|
|
Packit |
8681c6 |
CKD_SHA1_KDF,
|
|
Packit |
8681c6 |
CKD_SHA224_KDF,
|
|
Packit |
8681c6 |
CKD_SHA256_KDF,
|
|
Packit |
8681c6 |
CKD_SHA384_KDF,
|
|
Packit |
8681c6 |
CKD_SHA512_KDF,
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static const char *p11_get_ckd(CK_EC_KDF_TYPE kdf)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
switch (kdf) {
|
|
Packit |
8681c6 |
case CKD_NULL:
|
|
Packit |
8681c6 |
return "CKD_NULL";
|
|
Packit |
8681c6 |
case CKD_SHA1_KDF:
|
|
Packit |
8681c6 |
return "CKD_SHA1_KDF";
|
|
Packit |
8681c6 |
case CKD_SHA224_KDF:
|
|
Packit |
8681c6 |
return "CKD_SHA224_KDF";
|
|
Packit |
8681c6 |
case CKD_SHA256_KDF:
|
|
Packit |
8681c6 |
return "CKD_SHA256_KDF";
|
|
Packit |
8681c6 |
case CKD_SHA384_KDF:
|
|
Packit |
8681c6 |
return "CKD_SHA384_KDF";
|
|
Packit |
8681c6 |
case CKD_SHA512_KDF:
|
|
Packit |
8681c6 |
return "CKD_SHA512_KDF";
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
return "UNKNOWN";
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static unsigned int curve_len(int index)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
if (index >= NUMEC)
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return der_ec_supported[index].bit_len / 8;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV curve_supported(const char *name)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
if (name[strlen(name) - 2] == 'r' || name[strlen(name) - 2] == 'v')
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/**
|
|
Packit |
8681c6 |
* A test is skipped, when no KDF is used and the derived key length
|
|
Packit |
8681c6 |
* shall be bigger than the shared secret (z-value). Without a KDF, max
|
|
Packit |
8681c6 |
* z-length key bytes can be derived.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
static unsigned int too_many_key_bytes_requested(unsigned int curve,
|
|
Packit |
8681c6 |
unsigned int kdf,
|
|
Packit |
8681c6 |
unsigned int keylen)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
if (kdf > 0 || keylen <= curve_len(curve))
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* Generate EC key-pairs for parties A and B.
|
|
Packit |
8681c6 |
* Derive shared secrets based on Diffie Hellman key agreement defined in PKCS#3
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
CK_RV run_DeriveECDHKey()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE session;
|
|
Packit |
8681c6 |
CK_MECHANISM mech;
|
|
Packit |
8681c6 |
CK_FLAGS flags;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_keyA = CK_INVALID_HANDLE,
|
|
Packit |
8681c6 |
priv_keyA = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_keyB = CK_INVALID_HANDLE,
|
|
Packit |
8681c6 |
priv_keyB = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE secret_keyA = CK_INVALID_HANDLE,
|
|
Packit |
8681c6 |
secret_keyB = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
Packit |
8681c6 |
CK_ULONG user_pin_len;
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
CK_ECDH1_DERIVE_PARAMS ecdh_parmA, ecdh_parmB;
|
|
Packit |
8681c6 |
CK_BBOOL true = CK_TRUE;
|
|
Packit |
8681c6 |
CK_BBOOL false = CK_FALSE;
|
|
Packit |
8681c6 |
CK_BYTE pubkeyA_value[256];
|
|
Packit |
8681c6 |
CK_BYTE pubkeyB_value[256];
|
|
Packit |
8681c6 |
CK_BYTE secretA_value[80000]; //enough space for lengths in secret_key_len[]
|
|
Packit |
8681c6 |
CK_BYTE deriveB_value[80000];
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
|
|
Packit |
8681c6 |
CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
|
|
Packit |
8681c6 |
CK_ULONG i, j, k, m;
|
|
Packit |
8681c6 |
CK_MECHANISM_TYPE derive_mech_type;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_begin("starting run_DeriveECDHKey...");
|
|
Packit |
8681c6 |
testcase_rw_session();
|
|
Packit |
8681c6 |
testcase_user_login();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!mech_supported(SLOT_ID, CKM_EC_KEY_PAIR_GEN)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support CKM_EC_KEY_PAIR_GEN\n",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i=0; i
|
|
Packit |
8681c6 |
CK_ATTRIBUTE prv_attr[] = {
|
|
Packit |
8681c6 |
{CKA_SIGN, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_DERIVE, &true, sizeof(true)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG prv_attr_len = sizeof(prv_attr)/sizeof(CK_ATTRIBUTE);
|
|
Packit Service |
8aa27d |
CK_ATTRIBUTE prv_attr_edwards[] = {
|
|
Packit Service |
8aa27d |
{CKA_SIGN, &true, sizeof(true)},
|
|
Packit Service |
8aa27d |
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
CK_ULONG prv_attr_edwards_len =
|
|
Packit Service |
8aa27d |
sizeof(prv_attr_edwards)/sizeof(CK_ATTRIBUTE);
|
|
Packit Service |
8aa27d |
CK_ATTRIBUTE prv_attr_montgomery[] = {
|
|
Packit Service |
8aa27d |
{CKA_DERIVE, &true, sizeof(true)},
|
|
Packit Service |
8aa27d |
{CKA_EXTRACTABLE, &true, sizeof(true)},
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
CK_ULONG prv_attr_montgomery_len =
|
|
Packit Service |
8aa27d |
sizeof(prv_attr_montgomery)/sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE pub_attr[] = {
|
|
Packit |
8681c6 |
{CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_supported[i].curve,
|
|
Packit |
8681c6 |
der_ec_supported[i].size},
|
|
Packit |
8681c6 |
{CKA_VERIFY, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_MODIFIABLE, &true, sizeof(true)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG pub_attr_len = sizeof(pub_attr)/sizeof(CK_ATTRIBUTE);
|
|
Packit Service |
8aa27d |
CK_ATTRIBUTE pub_attr_montgomery[] = {
|
|
Packit Service |
8aa27d |
{CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_supported[i].curve,
|
|
Packit Service |
8aa27d |
der_ec_supported[i].size},
|
|
Packit Service |
8aa27d |
{CKA_MODIFIABLE, &true, sizeof(true)},
|
|
Packit Service |
8aa27d |
{CKA_VERIFY, &true, sizeof(true)},
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
CK_ULONG pub_attr_montgomery_len =
|
|
Packit Service |
8aa27d |
sizeof(pub_attr_montgomery)/sizeof(CK_ATTRIBUTE);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
CK_ATTRIBUTE *prv_attr_gen = prv_attr;
|
|
Packit Service |
8aa27d |
CK_ULONG prv_attr_gen_len = prv_attr_len;
|
|
Packit Service |
8aa27d |
CK_ATTRIBUTE *pub_attr_gen = pub_attr;
|
|
Packit Service |
8aa27d |
CK_ULONG pub_attr_gen_len = pub_attr_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE extr1_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_EC_POINT, pubkeyA_value, sizeof(pubkeyA_value)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG extr1_tmpl_len = sizeof(extr1_tmpl)/sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE extr2_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_EC_POINT, pubkeyB_value, sizeof(pubkeyB_value)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG extr2_tmpl_len = sizeof(extr2_tmpl)/sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (der_ec_supported[i].type == CURVE_EDWARDS) {
|
|
Packit |
8681c6 |
testcase_skip("Edwards curves can not be used for ECDH derive");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!is_ep11_token(SLOT_ID)) {
|
|
Packit |
8681c6 |
if (der_ec_supported[i].twisted) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (der_ec_supported[i].curve == secp256k1) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (der_ec_supported[i].type != CURVE_BRAINPOOL &&
|
|
Packit |
8681c6 |
der_ec_supported[i].type != CURVE_PRIME ) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
derive_mech_type = CKM_ECDH1_DERIVE;
|
|
Packit |
8681c6 |
if (der_ec_supported[i].type == CURVE_MONTGOMERY) {
|
|
Packit |
8681c6 |
if (der_ec_supported[i].curve == curve25519)
|
|
Packit |
8681c6 |
derive_mech_type = CKM_IBM_EC_C25519;
|
|
Packit |
8681c6 |
if (der_ec_supported[i].curve == curve448)
|
|
Packit |
8681c6 |
derive_mech_type = CKM_IBM_EC_C448;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
prv_attr_gen = prv_attr_montgomery;
|
|
Packit Service |
8aa27d |
prv_attr_gen_len = prv_attr_montgomery_len;
|
|
Packit Service |
8aa27d |
pub_attr_gen = pub_attr_montgomery;
|
|
Packit Service |
8aa27d |
pub_attr_gen_len = pub_attr_montgomery_len;
|
|
Packit Service |
8aa27d |
} else if (der_ec_supported[i].type == CURVE_EDWARDS) {
|
|
Packit Service |
8aa27d |
prv_attr_gen = prv_attr_edwards;
|
|
Packit Service |
8aa27d |
prv_attr_gen_len = prv_attr_edwards_len;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (!mech_supported(SLOT_ID, derive_mech_type)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support %s\n",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, p11_get_ckm(derive_mech_type));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Testcase #1 - Generate 2 EC key pairs.
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// First, generate the EC key pair for party A
|
|
Packit |
8681c6 |
mech.mechanism = CKM_EC_KEY_PAIR_GEN;
|
|
Packit |
8681c6 |
mech.ulParameterLen = 0;
|
|
Packit |
8681c6 |
mech.pParameter = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_GenerateKeyPair(session, &mech,
|
|
Packit Service |
8aa27d |
pub_attr_gen, pub_attr_gen_len,
|
|
Packit Service |
8aa27d |
prv_attr_gen, prv_attr_gen_len,
|
|
Packit |
8681c6 |
&publ_keyA, &priv_keyA);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
Packit Service |
8aa27d |
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
Packit Service |
8aa27d |
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_fail("C_GenerateKeyPair with valid input failed at i=%lu "
|
|
Packit |
8681c6 |
"(%s), rc=%s", i, der_ec_supported[i].name,
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Extract public key A
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, publ_keyA,
|
|
Packit |
8681c6 |
extr1_tmpl, extr1_tmpl_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_GetAttributeValue #1: rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Now generate the EC key pair for party B
|
|
Packit |
8681c6 |
mech.mechanism = CKM_EC_KEY_PAIR_GEN;
|
|
Packit |
8681c6 |
mech.ulParameterLen = 0;
|
|
Packit |
8681c6 |
mech.pParameter = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_GenerateKeyPair(session, &mech,
|
|
Packit Service |
8aa27d |
pub_attr_gen, pub_attr_gen_len,
|
|
Packit Service |
8aa27d |
prv_attr_gen, prv_attr_gen_len,
|
|
Packit |
8681c6 |
&publ_keyB, &priv_keyB);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_fail("C_GenerateKeyPair with valid input failed at i=%lu "
|
|
Packit |
8681c6 |
"(%s), rc=%s", i, der_ec_supported[i].name,
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Extract public key B
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, publ_keyB,
|
|
Packit |
8681c6 |
extr2_tmpl, extr2_tmpl_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_GetAttributeValue #1: rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Check if the key lengths are equal
|
|
Packit |
8681c6 |
if (extr1_tmpl->ulValueLen != extr2_tmpl->ulValueLen) {
|
|
Packit |
8681c6 |
testcase_error("Length of public key A not equal to length of "
|
|
Packit |
8681c6 |
"public key B");
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Testcase #2 - Now derive the secrets...
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (j=0; j < NUM_KDFS; j++) {
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (k=0; k
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (too_many_key_bytes_requested(i, j, secret_key_len[k])) {
|
|
Packit |
8681c6 |
testcase_skip("Cannot provide %lu key bytes with curve %s"
|
|
Packit |
8681c6 |
" without a kdf.\n", secret_key_len[k],
|
|
Packit |
8681c6 |
der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) && k > 8) {
|
|
Packit |
8681c6 |
testcase_skip("EP11 cannot provide %lu key bytes with "
|
|
Packit |
8681c6 |
"curve %s\n", secret_key_len[k],
|
|
Packit |
8681c6 |
der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE secretA_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_VALUE, secretA_value, sizeof(secretA_value)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG secretA_tmpl_len =
|
|
Packit |
8681c6 |
sizeof(secretA_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE secretB_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_VALUE, deriveB_value, sizeof(deriveB_value)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG secretB_tmpl_len =
|
|
Packit |
8681c6 |
sizeof(secretB_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE derive_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &class, sizeof(class)},
|
|
Packit |
8681c6 |
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
Packit |
8681c6 |
{CKA_VALUE_LEN, &(secret_key_len[k]), sizeof(CK_ULONG)},
|
|
Packit |
8681c6 |
{CKA_SENSITIVE, &false, sizeof(false)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG secret_tmpl_len =
|
|
Packit |
8681c6 |
sizeof(derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (m=0; m < (kdfs[j] == CKD_NULL ? 1 : NUM_SHARED_DATA); m++) {
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
testcase_begin("Starting with curve=%s, kdf=%s, keylen=%lu, "
|
|
Packit |
8681c6 |
"shared_data=%u, mech=%s",
|
|
Packit |
8681c6 |
der_ec_supported[i].name,
|
|
Packit |
8681c6 |
p11_get_ckd(kdfs[j]), secret_key_len[k],
|
|
Packit |
8681c6 |
shared_data[m].length,
|
|
Packit |
8681c6 |
p11_get_ckm(derive_mech_type));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Now, derive a generic secret key using party A's private
|
|
Packit |
8681c6 |
// key and B's public key
|
|
Packit |
8681c6 |
ecdh_parmA.kdf = kdfs[j];
|
|
Packit |
8681c6 |
ecdh_parmA.pPublicData = extr2_tmpl->pValue;
|
|
Packit |
8681c6 |
ecdh_parmA.ulPublicDataLen = extr2_tmpl->ulValueLen;
|
|
Packit |
8681c6 |
ecdh_parmA.pSharedData =
|
|
Packit |
8681c6 |
shared_data[m].length == 0 ?
|
|
Packit |
8681c6 |
NULL : (CK_BYTE_PTR) &shared_data[m].data;
|
|
Packit |
8681c6 |
ecdh_parmA.ulSharedDataLen = shared_data[m].length;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (kdfs[j] == CKD_NULL) {
|
|
Packit |
8681c6 |
ecdh_parmA.pSharedData = NULL;
|
|
Packit |
8681c6 |
ecdh_parmA.ulSharedDataLen = 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech.mechanism = derive_mech_type;
|
|
Packit |
8681c6 |
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
Packit |
8681c6 |
mech.pParameter = &ecdh_parmA;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_DeriveKey(session, &mech,
|
|
Packit |
8681c6 |
priv_keyA, derive_tmpl,
|
|
Packit |
8681c6 |
secret_tmpl_len, &secret_keyA);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
Packit |
8681c6 |
(kdfs[j] != CKD_NULL ||
|
|
Packit |
8681c6 |
shared_data[m].length > 0)) {
|
|
Packit |
8681c6 |
testcase_skip("EP11 does not support KDFs and "
|
|
Packit |
8681c6 |
"shared data with older firmware "
|
|
Packit |
8681c6 |
"versions\n");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail("C_DeriveKey #1: rc = %s",
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Now, derive a generic secret key using B's private key
|
|
Packit |
8681c6 |
// and A's public key
|
|
Packit |
8681c6 |
ecdh_parmB.kdf = kdfs[j];
|
|
Packit |
8681c6 |
ecdh_parmB.pPublicData = extr1_tmpl->pValue;
|
|
Packit |
8681c6 |
ecdh_parmB.ulPublicDataLen = extr1_tmpl->ulValueLen;
|
|
Packit |
8681c6 |
ecdh_parmB.pSharedData =
|
|
Packit |
8681c6 |
shared_data[m].length == 0 ?
|
|
Packit |
8681c6 |
NULL : (CK_BYTE_PTR)&shared_data[m].data;
|
|
Packit |
8681c6 |
ecdh_parmB.ulSharedDataLen = shared_data[m].length;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (kdfs[j] == CKD_NULL) {
|
|
Packit |
8681c6 |
ecdh_parmB.pSharedData = NULL;
|
|
Packit |
8681c6 |
ecdh_parmB.ulSharedDataLen = 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech.mechanism = derive_mech_type;
|
|
Packit |
8681c6 |
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
Packit |
8681c6 |
mech.pParameter = &ecdh_parmB;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_DeriveKey(session, &mech,
|
|
Packit |
8681c6 |
priv_keyB, derive_tmpl,
|
|
Packit |
8681c6 |
secret_tmpl_len, &secret_keyB);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
Packit |
8681c6 |
(kdfs[j] != CKD_NULL ||
|
|
Packit |
8681c6 |
shared_data[m].length > 0)) {
|
|
Packit |
8681c6 |
testcase_skip("EP11 does not support KDFs and "
|
|
Packit |
8681c6 |
"shared data with older firmware "
|
|
Packit |
8681c6 |
"versions\n");
|
|
Packit |
8681c6 |
if (secret_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyA);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail("C_DeriveKey #2: rc = %s",
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Extract the derived secret A
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, secret_keyA,
|
|
Packit |
8681c6 |
secretA_tmpl,
|
|
Packit |
8681c6 |
secretA_tmpl_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_GetAttributeValue #3:rc = %s",
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Extract the derived secret B
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, secret_keyB,
|
|
Packit |
8681c6 |
secretB_tmpl,
|
|
Packit |
8681c6 |
secretB_tmpl_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_GetAttributeValue #4:rc = %s",
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Compare lengths of derived secrets from key object
|
|
Packit |
8681c6 |
if (secretA_tmpl[0].ulValueLen !=
|
|
Packit |
8681c6 |
secretB_tmpl[0].ulValueLen) {
|
|
Packit |
8681c6 |
testcase_fail("ERROR: derived key #1 length = %ld, "
|
|
Packit |
8681c6 |
"derived key #2 length = %ld",
|
|
Packit |
8681c6 |
secretA_tmpl[0].ulValueLen,
|
|
Packit |
8681c6 |
secretB_tmpl[0].ulValueLen);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Compare derive secrets A and B
|
|
Packit |
8681c6 |
if (memcmp(secretA_tmpl[0].pValue,
|
|
Packit |
8681c6 |
secretB_tmpl[0].pValue,
|
|
Packit |
8681c6 |
secretA_tmpl[0].ulValueLen) != 0) {
|
|
Packit |
8681c6 |
testcase_fail("ERROR: derived key mismatch, curve=%s, "
|
|
Packit |
8681c6 |
"kdf=%s, keylen=%lu, shared_data=%u",
|
|
Packit |
8681c6 |
der_ec_supported[i].name,
|
|
Packit |
8681c6 |
p11_get_ckd(kdfs[j]), secret_key_len[k],
|
|
Packit |
8681c6 |
shared_data[m].length);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_pass("*Derive shared secret curve=%s, kdf=%s, "
|
|
Packit |
8681c6 |
"keylen=%lu, shared_data=%u, mech=%s passed.",
|
|
Packit |
8681c6 |
der_ec_supported[i].name,
|
|
Packit |
8681c6 |
p11_get_ckd(kdfs[j]), secret_key_len[k],
|
|
Packit |
8681c6 |
shared_data[m].length,
|
|
Packit |
8681c6 |
p11_get_ckm(derive_mech_type));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (secret_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyA);
|
|
Packit |
8681c6 |
if (secret_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyB);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (publ_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyA);
|
|
Packit |
8681c6 |
if (priv_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyA);
|
|
Packit |
8681c6 |
if (priv_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyB);
|
|
Packit |
8681c6 |
if (publ_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyB);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_cleanup:
|
|
Packit |
8681c6 |
if (publ_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyA);
|
|
Packit |
8681c6 |
if (priv_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyA);
|
|
Packit |
8681c6 |
if (priv_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyB);
|
|
Packit |
8681c6 |
if (publ_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyB);
|
|
Packit |
8681c6 |
if (secret_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyA);
|
|
Packit |
8681c6 |
if (secret_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyB);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_user_logout();
|
|
Packit |
8681c6 |
testcase_close_session();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
} /* end run_DeriveECDHKey() */
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* Run some ECDH known answer tests.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
CK_RV run_DeriveECDHKeyKAT()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE session;
|
|
Packit |
8681c6 |
CK_MECHANISM mech;
|
|
Packit |
8681c6 |
CK_FLAGS flags;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_keyA = CK_INVALID_HANDLE,
|
|
Packit |
8681c6 |
priv_keyA = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_keyB = CK_INVALID_HANDLE,
|
|
Packit |
8681c6 |
priv_keyB = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE secret_keyA = CK_INVALID_HANDLE,
|
|
Packit |
8681c6 |
secret_keyB = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
Packit |
8681c6 |
CK_KEY_TYPE secret_key_type = CKK_GENERIC_SECRET;
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
|
|
Packit |
8681c6 |
CK_ECDH1_DERIVE_PARAMS ecdh_parmA, ecdh_parmB;
|
|
Packit |
8681c6 |
CK_BBOOL false = CK_FALSE;
|
|
Packit |
8681c6 |
CK_ULONG user_pin_len;
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
CK_BYTE secretA_value[1000]; // enough space for key lengths in ecdh_tv[]
|
|
Packit |
8681c6 |
CK_BYTE secretB_value[1000];
|
|
Packit |
8681c6 |
CK_ULONG i;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_begin("starting run_DeriveECDHKeyKAT...");
|
|
Packit |
8681c6 |
testcase_rw_session();
|
|
Packit |
8681c6 |
testcase_user_login();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!mech_supported(SLOT_ID, CKM_ECDH1_DERIVE)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support CKM_ECDH1_DERIVE\n",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u is a secure key token, can not run known answer "
|
|
Packit |
8681c6 |
"tests with CKM_ECDH1_DERIVE on it\n",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i=0; i
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
testcase_begin("Starting with shared secret i=%lu", i);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// First, import the EC key pair for party A
|
|
Packit |
8681c6 |
rc = create_ECPrivateKey(session,
|
|
Packit |
8681c6 |
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
Packit |
8681c6 |
ecdh_tv[i].privkeyA, ecdh_tv[i].privkey_len,
|
|
Packit |
8681c6 |
ecdh_tv[i].pubkeyA, ecdh_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&priv_keyA);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
Packit Service |
8aa27d |
goto testcase_next;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, "
|
|
Packit |
8681c6 |
"rc=%s", i, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = create_ECPublicKey(session,
|
|
Packit |
8681c6 |
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
Packit |
8681c6 |
ecdh_tv[i].pubkeyA, ecdh_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&publ_keyA);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
Packit Service |
8aa27d |
goto testcase_next;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, "
|
|
Packit |
8681c6 |
"rc=%s", i, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Now import the EC key pair for party B
|
|
Packit |
8681c6 |
rc = create_ECPrivateKey(session,
|
|
Packit |
8681c6 |
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
Packit |
8681c6 |
ecdh_tv[i].privkeyB, ecdh_tv[i].privkey_len,
|
|
Packit |
8681c6 |
ecdh_tv[i].pubkeyB, ecdh_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&priv_keyB);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
Packit Service |
8aa27d |
goto testcase_next;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, "
|
|
Packit |
8681c6 |
"rc=%s", i, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = create_ECPublicKey(session,
|
|
Packit |
8681c6 |
ecdh_tv[i].params, ecdh_tv[i].params_len,
|
|
Packit |
8681c6 |
ecdh_tv[i].pubkeyB, ecdh_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&publ_keyB);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ecdh_tv[i].name);
|
|
Packit Service |
8aa27d |
goto testcase_next;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, "
|
|
Packit |
8681c6 |
"rc=%s", i, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Now derive the secrets...
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE secretA_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_VALUE, secretA_value, sizeof(secretA_value)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG secretA_tmpl_len = sizeof(secretA_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE secretB_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_VALUE, secretB_value, sizeof(secretB_value)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG secretB_tmpl_len = sizeof(secretB_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE derive_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &class, sizeof(class)},
|
|
Packit |
8681c6 |
{CKA_KEY_TYPE, &secret_key_type, sizeof(secret_key_type)},
|
|
Packit |
8681c6 |
{CKA_VALUE_LEN, &(ecdh_tv[i].derived_key_len), sizeof(CK_ULONG)},
|
|
Packit |
8681c6 |
{CKA_SENSITIVE, &false, sizeof(false)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
CK_ULONG derive_tmpl_len = sizeof(derive_tmpl) / sizeof(CK_ATTRIBUTE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Now, derive a generic secret key using party A's private key
|
|
Packit |
8681c6 |
// and B's public key
|
|
Packit |
8681c6 |
ecdh_parmA.kdf = ecdh_tv[i].kdf;
|
|
Packit |
8681c6 |
ecdh_parmA.pPublicData = ecdh_tv[i].pubkeyB;
|
|
Packit |
8681c6 |
ecdh_parmA.ulPublicDataLen = ecdh_tv[i].pubkey_len;
|
|
Packit |
8681c6 |
ecdh_parmA.pSharedData =
|
|
Packit |
8681c6 |
ecdh_tv[i].shared_data_len == 0 ?
|
|
Packit |
8681c6 |
NULL : (CK_BYTE_PTR)&ecdh_tv[i].shared_data;
|
|
Packit |
8681c6 |
ecdh_parmA.ulSharedDataLen = ecdh_tv[i].shared_data_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (ecdh_tv[i].kdf == CKD_NULL) {
|
|
Packit |
8681c6 |
ecdh_parmA.pSharedData = NULL;
|
|
Packit |
8681c6 |
ecdh_parmA.ulSharedDataLen = 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech.mechanism = CKM_ECDH1_DERIVE;
|
|
Packit |
8681c6 |
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
Packit |
8681c6 |
mech.pParameter = &ecdh_parmA;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_DeriveKey(session, &mech,
|
|
Packit |
8681c6 |
priv_keyA, derive_tmpl,
|
|
Packit |
8681c6 |
derive_tmpl_len, &secret_keyA);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
Packit |
8681c6 |
(ecdh_tv[i].kdf != CKD_NULL ||
|
|
Packit |
8681c6 |
ecdh_tv[i].shared_data_len > 0)) {
|
|
Packit |
8681c6 |
testcase_skip("EP11 does not support KDFs and shared data with "
|
|
Packit |
8681c6 |
"older firmware versions\n");
|
|
Packit |
8681c6 |
if (priv_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyA);
|
|
Packit |
8681c6 |
if (publ_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyA);
|
|
Packit |
8681c6 |
if (priv_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyB);
|
|
Packit |
8681c6 |
if (publ_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyB);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail("C_DeriveKey #1: rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Now, derive a generic secret key using B's private key and
|
|
Packit |
8681c6 |
// A's public key
|
|
Packit |
8681c6 |
ecdh_parmB.kdf = ecdh_tv[i].kdf;
|
|
Packit |
8681c6 |
ecdh_parmB.pPublicData = ecdh_tv[i].pubkeyA;
|
|
Packit |
8681c6 |
ecdh_parmB.ulPublicDataLen = ecdh_tv[i].pubkey_len;
|
|
Packit |
8681c6 |
ecdh_parmB.pSharedData =
|
|
Packit |
8681c6 |
ecdh_tv[i].shared_data_len == 0 ?
|
|
Packit |
8681c6 |
NULL : (CK_BYTE_PTR)&ecdh_tv[i].shared_data;
|
|
Packit |
8681c6 |
ecdh_parmB.ulSharedDataLen = ecdh_tv[i].shared_data_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (ecdh_tv[i].kdf == CKD_NULL) {
|
|
Packit |
8681c6 |
ecdh_parmB.pSharedData = NULL;
|
|
Packit |
8681c6 |
ecdh_parmB.ulSharedDataLen = 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech.mechanism = CKM_ECDH1_DERIVE;
|
|
Packit |
8681c6 |
mech.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
|
|
Packit |
8681c6 |
mech.pParameter = &ecdh_parmB;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_DeriveKey(session, &mech,
|
|
Packit |
8681c6 |
priv_keyB, derive_tmpl,
|
|
Packit |
8681c6 |
derive_tmpl_len, &secret_keyB);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_MECHANISM_PARAM_INVALID &&
|
|
Packit |
8681c6 |
(ecdh_tv[i].kdf != CKD_NULL ||
|
|
Packit |
8681c6 |
ecdh_tv[i].shared_data_len > 0)) {
|
|
Packit |
8681c6 |
testcase_skip("EP11 does not support KDFs and shared data with "
|
|
Packit |
8681c6 |
"older firmware versions\n");
|
|
Packit |
8681c6 |
if (secret_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyA);
|
|
Packit |
8681c6 |
if (priv_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyA);
|
|
Packit |
8681c6 |
if (publ_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyA);
|
|
Packit |
8681c6 |
if (priv_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyB);
|
|
Packit |
8681c6 |
if (publ_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyB);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail("C_DeriveKey #2: rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Extract the derived secret A
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, secret_keyA,
|
|
Packit |
8681c6 |
secretA_tmpl, secretA_tmpl_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_GetAttributeValue #3:rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Compare lengths of derived secret from key object
|
|
Packit |
8681c6 |
if (ecdh_tv[i].derived_key_len != secretA_tmpl[0].ulValueLen) {
|
|
Packit |
8681c6 |
testcase_fail("ERROR:derived key #1 length = %ld, "
|
|
Packit |
8681c6 |
"derived key #2 length = %ld",
|
|
Packit |
8681c6 |
ecdh_tv[i].derived_key_len,
|
|
Packit |
8681c6 |
secretA_tmpl[0].ulValueLen);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Compare with known value
|
|
Packit |
8681c6 |
if (memcmp(secretA_tmpl[0].pValue,
|
|
Packit |
8681c6 |
ecdh_tv[i].derived_key, ecdh_tv[i].derived_key_len) != 0) {
|
|
Packit |
8681c6 |
testcase_fail("ERROR:derived key mismatch, i=%lu",i);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Extract the derived secret B
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, secret_keyB,
|
|
Packit |
8681c6 |
secretB_tmpl, secretB_tmpl_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_GetAttributeValue #4:rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Compare lengths of derived secret from key object
|
|
Packit |
8681c6 |
if (ecdh_tv[i].derived_key_len != secretB_tmpl[0].ulValueLen) {
|
|
Packit |
8681c6 |
testcase_fail("ERROR:derived key #1 length = %ld, derived key #2 "
|
|
Packit |
8681c6 |
"length = %ld", ecdh_tv[i].derived_key_len,
|
|
Packit |
8681c6 |
secretB_tmpl[0].ulValueLen);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Compare with known value
|
|
Packit |
8681c6 |
if (memcmp(secretB_tmpl[0].pValue,
|
|
Packit |
8681c6 |
ecdh_tv[i].derived_key, ecdh_tv[i].derived_key_len) != 0) {
|
|
Packit |
8681c6 |
testcase_fail("ERROR:derived key mismatch, i=%lu",i);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_pass("*Derive shared secret i=%lu passed.", i);
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
testcase_next:
|
|
Packit |
8681c6 |
if (priv_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyA);
|
|
Packit |
8681c6 |
if (publ_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyA);
|
|
Packit |
8681c6 |
if (priv_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyB);
|
|
Packit |
8681c6 |
if (publ_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyB);
|
|
Packit |
8681c6 |
if (secret_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyA);
|
|
Packit |
8681c6 |
if (secret_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyB);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_cleanup:
|
|
Packit |
8681c6 |
if (priv_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyA);
|
|
Packit |
8681c6 |
if (publ_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyA);
|
|
Packit |
8681c6 |
if (priv_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_keyB);
|
|
Packit |
8681c6 |
if (publ_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_keyB);
|
|
Packit |
8681c6 |
if (secret_keyA != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyA);
|
|
Packit |
8681c6 |
if (secret_keyB != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_keyB);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_user_logout();
|
|
Packit |
8681c6 |
testcase_close_session();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
} /* end run_DeriveECDHKeyKAT() */
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV run_GenerateSignVerifyECC(CK_SESSION_HANDLE session,
|
|
Packit |
8681c6 |
CK_MECHANISM_TYPE mechType,
|
|
Packit |
8681c6 |
CK_ULONG inputlen,
|
|
Packit |
8681c6 |
CK_ULONG parts,
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE priv_key,
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_key,
|
|
Packit Service |
8aa27d |
enum curve_type curve_type,
|
|
Packit Service |
8aa27d |
CK_BYTE *params, CK_ULONG params_len)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_MECHANISM mech2;
|
|
Packit |
8681c6 |
CK_BYTE_PTR data = NULL, signature = NULL;
|
|
Packit |
8681c6 |
CK_ULONG i, signaturelen;
|
|
Packit |
8681c6 |
CK_MECHANISM_INFO mech_info;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_begin("Starting with mechtype='%s', inputlen=%lu parts=%lu",
|
|
Packit |
8681c6 |
p11_get_ckm(mechType), inputlen, parts);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech2.mechanism = mechType;
|
|
Packit |
8681c6 |
mech2.ulParameterLen = 0;
|
|
Packit |
8681c6 |
mech2.pParameter = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* query the slot, check if this mech if supported */
|
|
Packit |
8681c6 |
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech2.mechanism, &mech_info);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (rc == CKR_MECHANISM_INVALID) {
|
|
Packit |
8681c6 |
/* no support for EC key gen? skip */
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, p11_get_ckm(mechType));
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if ((mechType == CKM_IBM_ED25519_SHA512 || mechType == CKM_IBM_ED448_SHA3)) {
|
|
Packit |
8681c6 |
if (curve_type != CURVE_EDWARDS) {
|
|
Packit |
8681c6 |
/* Mechanism does not match to curve type, skip */
|
|
Packit |
8681c6 |
testcase_skip("Mechanism %s can only be used with Edwards curves",
|
|
Packit |
8681c6 |
p11_get_ckm(mechType));
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit Service |
8aa27d |
if (mechType == CKM_IBM_ED25519_SHA512 &&
|
|
Packit Service |
8aa27d |
memcmp(params, ed25519, MIN(params_len, sizeof(ed25519))) != 0) {
|
|
Packit Service |
8aa27d |
/* Mechanism does not match to curve, skip */
|
|
Packit Service |
8aa27d |
testcase_skip("Mechanism %s can only be used with Ed25519 curve",
|
|
Packit Service |
8aa27d |
p11_get_ckm(mechType));
|
|
Packit Service |
8aa27d |
rc = CKR_OK;
|
|
Packit Service |
8aa27d |
goto testcase_cleanup;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if (mechType == CKM_IBM_ED448_SHA3 &&
|
|
Packit Service |
8aa27d |
memcmp(params, ed448, MIN(params_len, sizeof(ed448))) != 0) {
|
|
Packit Service |
8aa27d |
/* Mechanism does not match to curve, skip */
|
|
Packit Service |
8aa27d |
testcase_skip("Mechanism %s can only be used with Ed448 curve",
|
|
Packit Service |
8aa27d |
p11_get_ckm(mechType));
|
|
Packit Service |
8aa27d |
rc = CKR_OK;
|
|
Packit Service |
8aa27d |
goto testcase_cleanup;
|
|
Packit Service |
8aa27d |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
if (curve_type == CURVE_EDWARDS || curve_type == CURVE_MONTGOMERY) {
|
|
Packit |
8681c6 |
/* Mechanism does not match to curve type, skip */
|
|
Packit |
8681c6 |
testcase_skip("Mechanism %s can not be used with Edwards/Montogmery curves",
|
|
Packit |
8681c6 |
p11_get_ckm(mechType));
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
data = calloc(sizeof(CK_BYTE), inputlen);
|
|
Packit |
8681c6 |
if (data == NULL) {
|
|
Packit |
8681c6 |
testcase_error("Can't allocate memory for %lu bytes",
|
|
Packit |
8681c6 |
sizeof(CK_BYTE) * inputlen);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i = 0; i < inputlen; i++) {
|
|
Packit |
8681c6 |
data[i] = (i + 1) % 255;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_SignInit(session, &mech2, priv_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (parts > 0) {
|
|
Packit |
8681c6 |
for (i = 0; i < parts; i++) {
|
|
Packit |
8681c6 |
rc = funcs->C_SignUpdate(session, data, inputlen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* get signature length */
|
|
Packit |
8681c6 |
rc = funcs->C_SignFinal(session, signature, &signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_SignFinal rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
rc = funcs->C_Sign(session, data, inputlen, NULL, &signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
signature = calloc(sizeof(CK_BYTE), signaturelen);
|
|
Packit |
8681c6 |
if (signature == NULL) {
|
|
Packit |
8681c6 |
testcase_error("Can't allocate memory for %lu bytes",
|
|
Packit |
8681c6 |
sizeof(CK_BYTE) * signaturelen);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (parts > 0) {
|
|
Packit |
8681c6 |
rc = funcs->C_SignFinal(session, signature, &signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_SignFinal rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
rc = funcs->C_Sign(session, data, inputlen, signature, &signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/****** Verify *******/
|
|
Packit |
8681c6 |
rc = funcs->C_VerifyInit(session, &mech2, publ_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (parts > 0) {
|
|
Packit |
8681c6 |
for (i = 0; i < parts; i++) {
|
|
Packit |
8681c6 |
rc = funcs->C_VerifyUpdate(session, data, inputlen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_VerifyFinal(session, signature, signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_VerifyFinal rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
rc = funcs->C_Verify(session, data, inputlen, signature, signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// corrupt the signature and re-verify
|
|
Packit |
8681c6 |
memcpy(signature, "ABCDEFGHIJKLMNOPQRSTUV",
|
|
Packit |
8681c6 |
strlen("ABCDEFGHIJKLMNOPQRSTUV"));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_VerifyInit(session, &mech2, publ_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (parts > 0) {
|
|
Packit |
8681c6 |
for (i = 0; i < parts; i++) {
|
|
Packit |
8681c6 |
rc = funcs->C_VerifyUpdate(session, data, inputlen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_VerifyFinal(session, signature, signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_SIGNATURE_INVALID) {
|
|
Packit |
8681c6 |
testcase_error("C_VerifyFinal rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
PRINT_ERR(" Expected CKR_SIGNATURE_INVALID\n");
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
rc = funcs->C_Verify(session, data, inputlen, signature, signaturelen);
|
|
Packit |
8681c6 |
if (rc != CKR_SIGNATURE_INVALID) {
|
|
Packit |
8681c6 |
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
PRINT_ERR(" Expected CKR_SIGNATURE_INVALID\n");
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_cleanup:
|
|
Packit |
8681c6 |
if (data)
|
|
Packit |
8681c6 |
free(data);
|
|
Packit |
8681c6 |
if (signature)
|
|
Packit |
8681c6 |
free(signature);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV run_GenerateECCKeyPairSignVerify()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_MECHANISM mech;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE session;
|
|
Packit |
8681c6 |
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
Packit |
8681c6 |
CK_ULONG user_pin_len, i, j;
|
|
Packit |
8681c6 |
CK_FLAGS flags;
|
|
Packit |
8681c6 |
CK_MECHANISM_INFO mech_info;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_begin("Starting ECC generate key pair.");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_rw_session();
|
|
Packit |
8681c6 |
testcase_user_login();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech.mechanism = CKM_EC_KEY_PAIR_GEN;
|
|
Packit |
8681c6 |
mech.ulParameterLen = 0;
|
|
Packit |
8681c6 |
mech.pParameter = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* query the slot, check if this mech is supported */
|
|
Packit |
8681c6 |
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (rc == CKR_MECHANISM_INVALID) {
|
|
Packit |
8681c6 |
/* no support for EC key gen? skip */
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support CKM_EC_KEY_PAIR_GEN",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID);
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i = 0; i < NUMEC; i++) {
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (der_ec_supported[i].type == CURVE_MONTGOMERY) {
|
|
Packit |
8681c6 |
testcase_skip("Montgomery curves can not be used for sign/verify");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!is_ep11_token(SLOT_ID)) {
|
|
Packit |
8681c6 |
if (der_ec_supported[i].twisted) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (der_ec_supported[i].curve == secp256k1) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (der_ec_supported[i].type != CURVE_BRAINPOOL &&
|
|
Packit |
8681c6 |
der_ec_supported[i].type != CURVE_PRIME ) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID,der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE ec_attr[] = {
|
|
Packit |
8681c6 |
{CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_supported[i].curve,
|
|
Packit |
8681c6 |
der_ec_supported[i].size}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_GenerateKeyPair(session, &mech, ec_attr, 1, NULL, 0,
|
|
Packit |
8681c6 |
&publ_key, &priv_key);
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (rc == CKR_MECHANISM_PARAM_INVALID ||
|
|
Packit Service |
8aa27d |
rc == CKR_ATTRIBUTE_VALUE_INVALID ||
|
|
Packit Service |
8aa27d |
rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_fail
|
|
Packit |
8681c6 |
("C_GenerateKeyPair with valid input failed at i=%lu (%s), "
|
|
Packit |
8681c6 |
"rc=%s", i, der_ec_supported[i].name, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Generate supported key pair index=%lu passed.", i);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (j = 0;
|
|
Packit |
8681c6 |
j < (sizeof(signVerifyInput) / sizeof(_signVerifyParam)); j++) {
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
rc = run_GenerateSignVerifyECC(session,
|
|
Packit |
8681c6 |
signVerifyInput[j].mechtype,
|
|
Packit |
8681c6 |
signVerifyInput[j].inputlen,
|
|
Packit |
8681c6 |
signVerifyInput[j].parts,
|
|
Packit |
8681c6 |
priv_key, publ_key,
|
|
Packit Service |
8aa27d |
der_ec_supported[i].type,
|
|
Packit Service |
8aa27d |
(CK_BYTE *)der_ec_supported[i].curve,
|
|
Packit Service |
8aa27d |
der_ec_supported[i].size);
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Sign & verify i=%lu, j=%lu passed.", i, j);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i = 0; i < NUMECINVAL; i++) {
|
|
Packit |
8681c6 |
CK_ATTRIBUTE ec_attr[] = {
|
|
Packit |
8681c6 |
{CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_notsupported[i].curve,
|
|
Packit |
8681c6 |
der_ec_notsupported[i].size}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_GenerateKeyPair(session, &mech, ec_attr, 1, NULL, 0,
|
|
Packit |
8681c6 |
&publ_key, &priv_key);
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
if (rc == CKR_OK) {
|
|
Packit |
8681c6 |
testcase_fail
|
|
Packit |
8681c6 |
("C_GenerateKeyPair with invalid input failed at i=%lu (%s)",
|
|
Packit |
8681c6 |
i, der_ec_supported[i].name);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Generate unsupported key pair curve=%s passed.",
|
|
Packit |
8681c6 |
der_ec_supported[i].name);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_cleanup:
|
|
Packit |
8681c6 |
if (publ_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_key);
|
|
Packit |
8681c6 |
if (priv_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_close_session();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV run_ImportECCKeyPairSignVerify()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_MECHANISM mech;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE session;
|
|
Packit |
8681c6 |
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
Packit |
8681c6 |
CK_ULONG user_pin_len, i, j;
|
|
Packit |
8681c6 |
CK_FLAGS flags;
|
|
Packit |
8681c6 |
CK_MECHANISM_INFO mech_info;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_begin("Starting ECC import key pair.");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_rw_session();
|
|
Packit |
8681c6 |
testcase_user_login();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech.mechanism = CKM_ECDSA;
|
|
Packit |
8681c6 |
mech.ulParameterLen = 0;
|
|
Packit |
8681c6 |
mech.pParameter = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* query the slot, check if this mech is supported */
|
|
Packit |
8681c6 |
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (rc == CKR_MECHANISM_INVALID) {
|
|
Packit |
8681c6 |
/* no support for EC key gen? skip */
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support CKM_ECDSA",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i = 0; i < EC_TV_NUM; i++) {
|
|
Packit |
8681c6 |
if ((is_ica_token(SLOT_ID) || is_cca_token(SLOT_ID))) {
|
|
Packit |
8681c6 |
if (!curve_supported((char *)ec_tv[i].name)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit |
8681c6 |
(unsigned int)SLOT_ID,ec_tv[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = create_ECPrivateKey(session, ec_tv[i].params, ec_tv[i].params_len,
|
|
Packit |
8681c6 |
ec_tv[i].privkey, ec_tv[i].privkey_len,
|
|
Packit |
8681c6 |
ec_tv[i].pubkey, ec_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&priv_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
Packit Service |
8aa27d |
continue;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
Packit |
8681c6 |
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
Packit |
8681c6 |
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
Packit |
8681c6 |
"older firmware versions",
|
|
Packit |
8681c6 |
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu "
|
|
Packit |
8681c6 |
"(%s), rc=%s", i, ec_tv[i].name, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Import EC private key (%s) index=%lu passed.",
|
|
Packit |
8681c6 |
ec_tv[i].name, i);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = create_ECPublicKey(session, ec_tv[i].params, ec_tv[i].params_len,
|
|
Packit |
8681c6 |
ec_tv[i].pubkey, ec_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&publ_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
Packit Service |
8aa27d |
funcs->C_DestroyObject(session, priv_key);
|
|
Packit Service |
8aa27d |
continue;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
Packit |
8681c6 |
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
Packit |
8681c6 |
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
Packit |
8681c6 |
"older firmware versions",
|
|
Packit |
8681c6 |
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_key);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu "
|
|
Packit |
8681c6 |
"(%s), rc=%s", i, ec_tv[i].name, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Import EC public key (%s) index=%lu passed.",
|
|
Packit |
8681c6 |
ec_tv[i].name, i);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* create signature with private key */
|
|
Packit |
8681c6 |
for (j = 0;
|
|
Packit |
8681c6 |
j < (sizeof(signVerifyInput) / sizeof(_signVerifyParam)); j++) {
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
rc = run_GenerateSignVerifyECC(session,
|
|
Packit |
8681c6 |
signVerifyInput[j].mechtype,
|
|
Packit |
8681c6 |
signVerifyInput[j].inputlen,
|
|
Packit |
8681c6 |
signVerifyInput[j].parts,
|
|
Packit |
8681c6 |
priv_key, publ_key,
|
|
Packit Service |
8aa27d |
ec_tv[i].curve_type,
|
|
Packit Service |
8aa27d |
ec_tv[i].params,
|
|
Packit Service |
8aa27d |
ec_tv[i].params_len);
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Sign & verify i=%lu, j=%lu passed.", i, j);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// clean up
|
|
Packit |
8681c6 |
rc = funcs->C_DestroyObject(session, publ_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_DestroyObject(session, priv_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_cleanup:
|
|
Packit |
8681c6 |
if (publ_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_key);
|
|
Packit |
8681c6 |
if (priv_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
testcase_user_logout();
|
|
Packit |
8681c6 |
testcase_close_session();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV run_TransferECCKeyPairSignVerify()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_MECHANISM mech;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE session;
|
|
Packit |
8681c6 |
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
Packit |
8681c6 |
CK_ULONG user_pin_len, i, j;
|
|
Packit |
8681c6 |
CK_FLAGS flags;
|
|
Packit |
8681c6 |
CK_MECHANISM_INFO mech_info;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
CK_MECHANISM aes_keygen_mech;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE secret_key = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_BYTE_PTR wrapped_key = NULL;
|
|
Packit |
8681c6 |
CK_ULONG wrapped_keylen;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
CK_MECHANISM wrap_mech;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_begin("Starting ECC transfer key pair.");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_rw_session();
|
|
Packit |
8681c6 |
testcase_user_login();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
mech.mechanism = CKM_ECDSA;
|
|
Packit |
8681c6 |
mech.ulParameterLen = 0;
|
|
Packit |
8681c6 |
mech.pParameter = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* query the slot, check if this mech is supported */
|
|
Packit |
8681c6 |
rc = funcs->C_GetMechanismInfo(SLOT_ID, mech.mechanism, &mech_info);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
if (rc == CKR_MECHANISM_INVALID) {
|
|
Packit |
8681c6 |
/* no support for EC key gen? skip */
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support CKM_ECDSA",
|
|
Packit |
8681c6 |
(unsigned int) SLOT_ID);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_KEY_GEN, &mech_info);
|
|
Packit Service |
8aa27d |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_MECHANISM_INVALID) {
|
|
Packit Service |
8aa27d |
/* no support for AES key gen? skip */
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support CKM_AES_KEY_GEN",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID);
|
|
Packit Service |
8aa27d |
goto testcase_cleanup;
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
Packit Service |
8aa27d |
goto testcase_cleanup;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_CBC_PAD, &mech_info);
|
|
Packit Service |
8aa27d |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_MECHANISM_INVALID) {
|
|
Packit Service |
8aa27d |
/* no support for AES CBC wrap? skip */
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID);
|
|
Packit Service |
8aa27d |
goto testcase_cleanup;
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc));
|
|
Packit Service |
8aa27d |
goto testcase_cleanup;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if ((mech_info.flags & CKF_WRAP) == 0 ||
|
|
Packit Service |
8aa27d |
(mech_info.flags & CKF_UNWRAP) == 0) {
|
|
Packit Service |
8aa27d |
/* no support for AES CBC wrap? skip */
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD for wrapping "
|
|
Packit Service |
8aa27d |
"keys", (unsigned int) SLOT_ID);
|
|
Packit Service |
8aa27d |
goto testcase_cleanup;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
for (i = 0; i < EC_TV_NUM; i++) {
|
|
Packit |
8681c6 |
if (!(is_ep11_token(SLOT_ID))) {
|
|
Packit |
8681c6 |
if (strstr((char *)ec_tv[i].name, "t1") != NULL) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support curve %s",
|
|
Packit |
8681c6 |
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
Packit |
8681c6 |
ec_tv[i].curve_type == CURVE_MONTGOMERY) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support curve %s",
|
|
Packit |
8681c6 |
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = create_ECPrivateKey(session, ec_tv[i].params, ec_tv[i].params_len,
|
|
Packit |
8681c6 |
ec_tv[i].privkey, ec_tv[i].privkey_len,
|
|
Packit |
8681c6 |
ec_tv[i].pubkey, ec_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&priv_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
Packit Service |
8aa27d |
continue;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
Packit |
8681c6 |
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
Packit |
8681c6 |
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
Packit |
8681c6 |
"older firmware versions",
|
|
Packit |
8681c6 |
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail
|
|
Packit |
8681c6 |
("C_CreateObject (EC Private Key) failed at i=%lu, rc=%s", i,
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Import EC private key (%s) index=%lu passed.",
|
|
Packit |
8681c6 |
ec_tv[i].name, i);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = create_ECPublicKey(session, ec_tv[i].params, ec_tv[i].params_len,
|
|
Packit |
8681c6 |
ec_tv[i].pubkey, ec_tv[i].pubkey_len,
|
|
Packit |
8681c6 |
&publ_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
if (rc == CKR_CURVE_NOT_SUPPORTED) {
|
|
Packit Service |
8aa27d |
testcase_skip("Slot %u doesn't support this curve: %s",
|
|
Packit Service |
8aa27d |
(unsigned int) SLOT_ID, ec_tv[i].name);
|
|
Packit Service |
8aa27d |
funcs->C_DestroyObject(session, priv_key);
|
|
Packit Service |
8aa27d |
continue;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
if (is_ep11_token(SLOT_ID) &&
|
|
Packit |
8681c6 |
rc == CKR_ENCRYPTED_DATA_INVALID &&
|
|
Packit |
8681c6 |
(ec_tv[i].curve_type == CURVE_EDWARDS ||
|
|
Packit |
8681c6 |
ec_tv[i].curve_type == CURVE_MONTGOMERY)) {
|
|
Packit |
8681c6 |
testcase_skip("Slot %u doesn't support this curve %s with "
|
|
Packit |
8681c6 |
"older firmware versions",
|
|
Packit |
8681c6 |
(unsigned int)SLOT_ID, ec_tv[i].name);
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_key);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_fail
|
|
Packit |
8681c6 |
("C_CreateObject (EC Public Key) failed at i=%lu, rc=%s", i,
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Import EC public key (%s) index=%lu passed.",
|
|
Packit |
8681c6 |
ec_tv[i].name, i);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* create wrapping key (secret key) */
|
|
Packit |
8681c6 |
aes_keygen_mech.mechanism = CKM_AES_KEY_GEN;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS wkclass = CKO_SECRET_KEY;
|
|
Packit |
8681c6 |
CK_ULONG keylen = 32;
|
|
Packit |
8681c6 |
CK_BBOOL true = TRUE;
|
|
Packit |
8681c6 |
CK_BYTE wrap_key_label[] = "Wrap_Key";
|
|
Packit |
8681c6 |
CK_ATTRIBUTE secret_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &wkclass, sizeof(wkclass)},
|
|
Packit |
8681c6 |
{CKA_VALUE_LEN, &keylen, sizeof(keylen)},
|
|
Packit |
8681c6 |
{CKA_LABEL, &wrap_key_label, sizeof(wrap_key_label)},
|
|
Packit |
8681c6 |
{CKA_TOKEN, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_WRAP, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_UNWRAP, &true, sizeof(true)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_GenerateKey(session, &aes_keygen_mech, secret_tmpl,
|
|
Packit |
8681c6 |
sizeof(secret_tmpl) / sizeof(CK_ATTRIBUTE),
|
|
Packit |
8681c6 |
&secret_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_GenerateKey, rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* wrap/unwrap private and public EC key with a transport key */
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// length only
|
|
Packit |
8681c6 |
wrap_mech.mechanism = CKM_AES_CBC_PAD;
|
|
Packit |
8681c6 |
wrap_mech.pParameter = "0123456789abcdef";
|
|
Packit |
8681c6 |
wrap_mech.ulParameterLen = 16;
|
|
Packit |
8681c6 |
rc = funcs->C_WrapKey(session, &wrap_mech, secret_key, priv_key,
|
|
Packit |
8681c6 |
NULL, &wrapped_keylen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_WrapKey(), rc=%s.", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// allocate memory for wrapped_key
|
|
Packit |
8681c6 |
wrapped_key = calloc(sizeof(CK_BYTE), wrapped_keylen);
|
|
Packit |
8681c6 |
if (wrapped_key == NULL) {
|
|
Packit |
8681c6 |
testcase_error("Can't allocate memory for %lu bytes.",
|
|
Packit |
8681c6 |
sizeof(CK_BYTE) * wrapped_keylen);
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// wrap key
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
rc = funcs->C_WrapKey(session, &wrap_mech, secret_key, priv_key,
|
|
Packit |
8681c6 |
wrapped_key, &wrapped_keylen);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_fail("C_WrapKey, rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// unwrap key
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
|
|
Packit |
8681c6 |
CK_KEY_TYPE key_type = CKK_EC;
|
|
Packit |
8681c6 |
CK_BYTE unwrap_label[] = "unwrapped_private_EC_Key";
|
|
Packit |
8681c6 |
CK_BYTE subject[] = {0};
|
|
Packit |
8681c6 |
CK_BYTE id[] = { 123 };
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE unwrap_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &class, sizeof(class)},
|
|
Packit |
8681c6 |
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
|
|
Packit |
8681c6 |
{CKA_TOKEN, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_LABEL, &unwrap_label, sizeof(unwrap_label)},
|
|
Packit |
8681c6 |
{CKA_SUBJECT, subject, sizeof(subject)},
|
|
Packit |
8681c6 |
{CKA_ID, id, sizeof(id)},
|
|
Packit |
8681c6 |
{CKA_SENSITIVE, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_DECRYPT, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_SIGN, &true, sizeof(true)},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_UnwrapKey(session, &wrap_mech, secret_key,
|
|
Packit |
8681c6 |
wrapped_key, wrapped_keylen,
|
|
Packit |
8681c6 |
unwrap_tmpl,
|
|
Packit |
8681c6 |
sizeof(unwrap_tmpl) / sizeof(CK_ATTRIBUTE),
|
|
Packit |
8681c6 |
&unwrapped_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_fail("C_UnwrapKey, rc=%s", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (wrapped_key) {
|
|
Packit |
8681c6 |
free(wrapped_key);
|
|
Packit |
8681c6 |
wrapped_key = NULL;
|
|
Packit Service |
8aa27d |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* create signature with unwrapped private key and verify with
|
|
Packit |
8681c6 |
* public key */
|
|
Packit |
8681c6 |
for (j = 0;
|
|
Packit |
8681c6 |
j < (sizeof(signVerifyInput) / sizeof(_signVerifyParam)); j++) {
|
|
Packit |
8681c6 |
testcase_new_assertion();
|
|
Packit |
8681c6 |
rc = run_GenerateSignVerifyECC(session,
|
|
Packit |
8681c6 |
signVerifyInput[j].mechtype,
|
|
Packit |
8681c6 |
signVerifyInput[j].inputlen,
|
|
Packit |
8681c6 |
signVerifyInput[j].parts,
|
|
Packit |
8681c6 |
unwrapped_key, publ_key,
|
|
Packit Service |
8aa27d |
ec_tv[i].curve_type,
|
|
Packit Service |
8aa27d |
ec_tv[i].params,
|
|
Packit Service |
8aa27d |
ec_tv[i].params_len);
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j);
|
|
Packit |
8681c6 |
goto testcase_cleanup;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
testcase_pass("*Sign & verify i=%lu, j=%lu passed.", i, j);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// clean up
|
|
Packit |
8681c6 |
rc = funcs->C_DestroyObject(session, publ_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_DestroyObject(session, priv_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_DestroyObject(session, secret_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
rc = funcs->C_DestroyObject(session, unwrapped_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(rc));
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_cleanup:
|
|
Packit |
8681c6 |
if (publ_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, publ_key);
|
|
Packit |
8681c6 |
if (priv_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, priv_key);
|
|
Packit |
8681c6 |
if (secret_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, secret_key);
|
|
Packit |
8681c6 |
if (unwrapped_key != CK_INVALID_HANDLE)
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(session, unwrapped_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (wrapped_key)
|
|
Packit |
8681c6 |
free(wrapped_key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
testcase_user_logout();
|
|
Packit |
8681c6 |
testcase_close_session();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int main(int argc, char **argv)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_C_INITIALIZE_ARGS cinit_args;
|
|
Packit |
8681c6 |
int rc;
|
|
Packit |
8681c6 |
CK_RV rv;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = do_ParseArgs(argc, argv);
|
|
Packit |
8681c6 |
if (rc != 1)
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
printf("Using slot #%lu...\n\n", SLOT_ID);
|
|
Packit |
8681c6 |
printf("With option: no_init: %d\n", no_init);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = do_GetFunctionList();
|
|
Packit |
8681c6 |
if (!rc) {
|
|
Packit |
8681c6 |
PRINT_ERR("ERROR do_GetFunctionList() Failed , rc = 0x%0x\n", rc);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(&cinit_args, 0x0, sizeof(cinit_args));
|
|
Packit |
8681c6 |
cinit_args.flags = CKF_OS_LOCKING_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// SAB Add calls to ALL functions before the C_Initialize gets hit
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
funcs->C_Initialize(&cinit_args);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE hsess = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_GetFunctionStatus(hsess);
|
|
Packit |
8681c6 |
if (rc != CKR_FUNCTION_NOT_PARALLEL)
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_CancelFunction(hsess);
|
|
Packit |
8681c6 |
if (rc != CKR_FUNCTION_NOT_PARALLEL)
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_setup(total_assertions);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rv = run_GenerateECCKeyPairSignVerify();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rv = run_ImportECCKeyPairSignVerify();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rv = run_TransferECCKeyPairSignVerify();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rv = run_DeriveECDHKey();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rv = run_DeriveECDHKeyKAT();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
testcase_print_result();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
funcs->C_Finalize(NULL);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* make sure we return non-zero if rv is non-zero */
|
|
Packit |
8681c6 |
return ((rv == 0) || (rv % 256) ? (int)rv : -1);
|
|
Packit |
8681c6 |
}
|