Blame usr/lib/common/mech_ec.c

Packit 8681c6
/*
Packit 8681c6
 * COPYRIGHT (c) International Business Machines Corp. 2001-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
/* File:  mech_ec.c
Packit 8681c6
 *
Packit 8681c6
 * Mechanisms for Elliptic Curve (EC)
Packit 8681c6
 */
Packit 8681c6
Packit Service 8aa27d
#define _GNU_SOURCE
Packit Service 8aa27d
#include <endian.h>
Packit 8681c6
#include <stdio.h>
Packit 8681c6
#include <stdlib.h>
Packit 8681c6
#include <stdint.h>
Packit 8681c6
#include <string.h>
Packit 8681c6
#include "pkcs11types.h"
Packit 8681c6
#include "defs.h"
Packit 8681c6
#include "host_defs.h"
Packit 8681c6
#include "h_extern.h"
Packit 8681c6
#include "tok_spec_struct.h"
Packit 8681c6
#include "trace.h"
Packit 8681c6
#include "tok_specific.h"
Packit 8681c6
#include "ec_defs.h"
Packit 8681c6
Packit 8681c6
#include "openssl/obj_mac.h"
Packit 8681c6
#include <openssl/ec.h>
Packit 8681c6
Packit 8681c6
#if OPENSSL_VERSION_NUMBER < 0x10100000L
Packit 8681c6
/*
Packit 8681c6
 * Older OpenSLL versions do not have BN_bn2binpad, so implement it here
Packit 8681c6
 */
Packit 8681c6
static int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
Packit 8681c6
{
Packit 8681c6
    int len, pad;
Packit 8681c6
    unsigned char *buf;
Packit 8681c6
Packit 8681c6
    len = BN_num_bytes(a);
Packit 8681c6
    buf = (unsigned char *)malloc(len);
Packit 8681c6
    if (buf == NULL)
Packit 8681c6
        return -1;
Packit 8681c6
    BN_bn2bin(a, buf);
Packit 8681c6
Packit 8681c6
    if (len >= tolen) {
Packit 8681c6
        memcpy(to, buf, tolen);
Packit 8681c6
    } else {
Packit 8681c6
        pad = tolen - len;
Packit 8681c6
        memset(to, 0, pad);
Packit 8681c6
        memcpy(to + pad, buf, len);
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    free(buf);
Packit 8681c6
    return tolen;
Packit 8681c6
}
Packit 8681c6
#endif
Packit 8681c6
Packit 8681c6
#ifndef NID_brainpoolP160r1
Packit 8681c6
/*
Packit 8681c6
 * Older OpenSLL versions may not have the brainpool NIDs defined, define them
Packit 8681c6
 * here
Packit 8681c6
 */
Packit 8681c6
#define NID_brainpoolP160r1             921
Packit 8681c6
#define NID_brainpoolP160t1             922
Packit 8681c6
#define NID_brainpoolP192r1             923
Packit 8681c6
#define NID_brainpoolP192t1             924
Packit 8681c6
#define NID_brainpoolP224r1             925
Packit 8681c6
#define NID_brainpoolP224t1             926
Packit 8681c6
#define NID_brainpoolP256r1             927
Packit 8681c6
#define NID_brainpoolP256t1             928
Packit 8681c6
#define NID_brainpoolP320r1             929
Packit 8681c6
#define NID_brainpoolP320t1             930
Packit 8681c6
#define NID_brainpoolP384r1             931
Packit 8681c6
#define NID_brainpoolP384t1             932
Packit 8681c6
#define NID_brainpoolP512r1             933
Packit 8681c6
#define NID_brainpoolP512t1             934
Packit 8681c6
Packit 8681c6
#endif
Packit 8681c6
Packit 8681c6
#ifndef NID_X25519
Packit 8681c6
#define NID_X25519                      1034
Packit 8681c6
#define NID_X448                        1035
Packit 8681c6
#endif
Packit 8681c6
#ifndef NID_ED25519
Packit 8681c6
#define NID_ED25519                     1087
Packit 8681c6
#define NID_ED448                       1088
Packit 8681c6
#endif
Packit 8681c6
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 struct _ec der_ec_supported[NUMEC] = {
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE160, NID_brainpoolP160r1,
Packit 8681c6
            sizeof(brainpoolP160r1), &brainpoolP160r1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE160, NID_brainpoolP160t1,
Packit 8681c6
            sizeof(brainpoolP160t1), &brainpoolP160t1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE192, NID_brainpoolP192r1,
Packit 8681c6
            sizeof(brainpoolP192r1), &brainpoolP192r1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE192, NID_brainpoolP192t1,
Packit 8681c6
            sizeof(brainpoolP192t1), &brainpoolP192t1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE224, NID_brainpoolP224r1,
Packit 8681c6
            sizeof(brainpoolP224r1), &brainpoolP224r1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE224, NID_brainpoolP224t1,
Packit 8681c6
            sizeof(brainpoolP224t1), &brainpoolP224t1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE256, NID_brainpoolP256r1,
Packit 8681c6
            sizeof(brainpoolP256r1), &brainpoolP256r1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE256, NID_brainpoolP256t1,
Packit 8681c6
            sizeof(brainpoolP256t1), &brainpoolP256t1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE320, NID_brainpoolP320r1,
Packit 8681c6
            sizeof(brainpoolP320r1), &brainpoolP320r1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE320, NID_brainpoolP320t1,
Packit 8681c6
            sizeof(brainpoolP320t1), &brainpoolP320t1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE384, NID_brainpoolP384r1,
Packit 8681c6
            sizeof(brainpoolP384r1), &brainpoolP384r1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE384, NID_brainpoolP384t1,
Packit 8681c6
            sizeof(brainpoolP384t1), &brainpoolP384t1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE512, NID_brainpoolP512r1,
Packit 8681c6
            sizeof(brainpoolP512r1), &brainpoolP512r1},
Packit 8681c6
    {BRAINPOOL_CURVE, CURVE512, NID_brainpoolP512t1,
Packit 8681c6
            sizeof(brainpoolP512t1), &brainpoolP512t1},
Packit 8681c6
    {PRIME_CURVE, CURVE192, NID_X9_62_prime192v1,
Packit 8681c6
            sizeof(prime192v1), &prime192v1},
Packit 8681c6
    {PRIME_CURVE, CURVE224, NID_secp224r1, sizeof(secp224r1), &secp224r1},
Packit 8681c6
    {PRIME_CURVE, CURVE256, NID_X9_62_prime256v1,
Packit 8681c6
            sizeof(prime256v1), &prime256v1},
Packit 8681c6
    {PRIME_CURVE, CURVE384, NID_secp384r1, sizeof(secp384r1), &secp384r1},
Packit 8681c6
    {PRIME_CURVE, CURVE521, NID_secp521r1, sizeof(secp521r1), &secp521r1},
Packit 8681c6
    {PRIME_CURVE, CURVE256, NID_secp256k1, sizeof(secp256k1), &secp256k1},
Packit 8681c6
    {MONTGOMERY_CURVE, CURVE256, NID_X25519, sizeof(curve25519), &curve25519},
Packit 8681c6
    {MONTGOMERY_CURVE, CURVE456, NID_X448, sizeof(curve448), &curve448},
Packit 8681c6
    {EDWARDS_CURVE, CURVE256, NID_ED25519, sizeof(ed25519), &ed25519},
Packit 8681c6
    {EDWARDS_CURVE, CURVE456, NID_ED448, sizeof(ed448), &ed448},
Packit 8681c6
};
Packit 8681c6
Packit 8681c6
Packit 8681c6
CK_RV get_ecsiglen(OBJECT *key_obj, CK_ULONG *size)
Packit 8681c6
{
Packit 8681c6
    CK_BBOOL flag;
Packit 8681c6
    CK_ATTRIBUTE *attr = NULL;
Packit 8681c6
    int i;
Packit 8681c6
Packit 8681c6
    flag = template_attribute_find(key_obj->template, CKA_ECDSA_PARAMS, &attr);
Packit 8681c6
    if (flag == FALSE) {
Packit 8681c6
        TRACE_ERROR("Could not find CKA_ECDSA_PARAMS for the key.\n");
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* loop thru supported curves to find the size.
Packit 8681c6
     * both pkcs#11v2.20 and CCA expect the signature length to be
Packit 8681c6
     * twice the length of p.
Packit 8681c6
     * (See EC Signatures in pkcs#11v2.20 and docs for CSNDDSG.)
Packit 8681c6
     */
Packit 8681c6
    for (i = 0; i < NUMEC; i++) {
Packit 8681c6
        if (!memcmp(attr->pValue, der_ec_supported[i].data,
Packit 8681c6
                    MIN(attr->ulValueLen, der_ec_supported[i].data_size))) {
Packit 8681c6
            *size = der_ec_supported[i].len_bits;
Packit 8681c6
            /* round up if necessary */
Packit 8681c6
            if ((*size % 8) == 0)
Packit 8681c6
                *size = (*size / 8) * 2;
Packit 8681c6
            else
Packit 8681c6
                *size = ((*size / 8) + 1) * 2;
Packit 8681c6
Packit 8681c6
            TRACE_DEVEL("getlen, curve = %d, size = %lu\n",
Packit 8681c6
                        der_ec_supported[i].len_bits, *size);
Packit 8681c6
            return CKR_OK;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID));
Packit 8681c6
Packit 8681c6
    return CKR_MECHANISM_PARAM_INVALID;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ckm_ec_key_pair_gen(STDLL_TokData_t *tokdata, TEMPLATE *publ_tmpl,
Packit 8681c6
                          TEMPLATE *priv_tmpl)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (token_specific.t_ec_generate_keypair == NULL) {
Packit 8681c6
        TRACE_ERROR("ec_generate_keypair not supported by this token\n");
Packit 8681c6
        return CKR_FUNCTION_NOT_SUPPORTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = token_specific.t_ec_generate_keypair(tokdata, publ_tmpl, priv_tmpl);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        TRACE_ERROR("Key Generation failed\n");
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ckm_ec_sign(STDLL_TokData_t *tokdata,
Packit 8681c6
                  SESSION *sess,
Packit 8681c6
                  CK_BYTE *in_data,
Packit 8681c6
                  CK_ULONG in_data_len,
Packit 8681c6
                  CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj)
Packit 8681c6
{
Packit 8681c6
    CK_ATTRIBUTE *attr = NULL;
Packit 8681c6
    CK_OBJECT_CLASS keyclass;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (token_specific.t_ec_sign == NULL) {
Packit 8681c6
        TRACE_ERROR("ec_sign not supported by this token\n");
Packit 8681c6
        return CKR_FUNCTION_NOT_SUPPORTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
Packit 8681c6
    if (rc == FALSE) {
Packit 8681c6
        TRACE_ERROR("Could not find CKA_CLASS in the template\n");
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    keyclass = *(CK_OBJECT_CLASS *) attr->pValue;
Packit 8681c6
Packit 8681c6
    // this had better be a private key
Packit 8681c6
    //
Packit 8681c6
    if (keyclass != CKO_PRIVATE_KEY) {
Packit 8681c6
        TRACE_ERROR("This operation requires a private key.\n");
Packit 8681c6
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = token_specific.t_ec_sign(tokdata, sess, in_data, in_data_len, out_data,
Packit 8681c6
                                  out_data_len, key_obj);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        TRACE_DEVEL("EC Sign failed.\n");
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ec_sign(STDLL_TokData_t *tokdata,
Packit 8681c6
              SESSION *sess,
Packit 8681c6
              CK_BBOOL length_only,
Packit 8681c6
              SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
              CK_BYTE *in_data,
Packit 8681c6
              CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len)
Packit 8681c6
{
Packit 8681c6
    OBJECT *key_obj = NULL;
Packit 8681c6
    CK_ULONG plen;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (!sess || !ctx || !out_data_len) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Failed to acquire key from specified handle");
Packit 8681c6
        if (rc == CKR_OBJECT_HANDLE_INVALID)
Packit 8681c6
            return CKR_KEY_HANDLE_INVALID;
Packit 8681c6
        else
Packit 8681c6
            return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = get_ecsiglen(key_obj, &plen);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("get_ecsiglen failed.\n");
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (length_only == TRUE) {
Packit 8681c6
        *out_data_len = plen;
Packit 8681c6
        rc = CKR_OK;
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (*out_data_len < plen) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
Packit 8681c6
        rc = CKR_BUFFER_TOO_SMALL;
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = ckm_ec_sign(tokdata, sess, in_data, in_data_len, out_data,
Packit 8681c6
                     out_data_len, key_obj);
Packit 8681c6
Packit 8681c6
done:
Packit 8681c6
    object_put(tokdata, key_obj, TRUE);
Packit 8681c6
    key_obj = NULL;
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ckm_ec_verify(STDLL_TokData_t *tokdata,
Packit 8681c6
                    SESSION *sess,
Packit 8681c6
                    CK_BYTE *in_data,
Packit 8681c6
                    CK_ULONG in_data_len,
Packit 8681c6
                    CK_BYTE *out_data, CK_ULONG out_data_len, OBJECT *key_obj)
Packit 8681c6
{
Packit 8681c6
    CK_ATTRIBUTE *attr = NULL;
Packit 8681c6
    CK_OBJECT_CLASS keyclass;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (token_specific.t_ec_verify == NULL) {
Packit 8681c6
        TRACE_ERROR("ec_verify not supported by this token\n");
Packit 8681c6
        return CKR_FUNCTION_NOT_SUPPORTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
Packit 8681c6
    if (rc == FALSE) {
Packit 8681c6
        TRACE_ERROR("Could not find CKA_CLASS in the template\n");
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    keyclass = *(CK_OBJECT_CLASS *) attr->pValue;
Packit 8681c6
Packit 8681c6
    // this had better be a public key
Packit 8681c6
    //
Packit 8681c6
    if (keyclass != CKO_PUBLIC_KEY) {
Packit 8681c6
        TRACE_ERROR("This operation requires a public key.\n");
Packit 8681c6
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = token_specific.t_ec_verify(tokdata, sess, in_data, in_data_len,
Packit 8681c6
                                    out_data, out_data_len, key_obj);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        TRACE_ERROR("Token specific ec verify failed.\n");
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ec_verify(STDLL_TokData_t *tokdata,
Packit 8681c6
                SESSION *sess,
Packit 8681c6
                SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
                CK_BYTE *in_data,
Packit 8681c6
                CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len)
Packit 8681c6
{
Packit 8681c6
    OBJECT *key_obj = NULL;
Packit 8681c6
    CK_ULONG plen;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Failed to acquire key from specified handle");
Packit 8681c6
        if (rc == CKR_OBJECT_HANDLE_INVALID)
Packit 8681c6
            return CKR_KEY_HANDLE_INVALID;
Packit 8681c6
        else
Packit 8681c6
            return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = get_ecsiglen(key_obj, &plen);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("get_ecsiglen failed.\n");
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
    // check input data length restrictions
Packit 8681c6
    //
Packit 8681c6
    if (sig_len > plen) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE));
Packit 8681c6
        rc = CKR_SIGNATURE_LEN_RANGE;
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
    rc = ckm_ec_verify(tokdata, sess, in_data, in_data_len, signature,
Packit 8681c6
                       sig_len, key_obj);
Packit 8681c6
Packit 8681c6
done:
Packit 8681c6
    object_put(tokdata, key_obj, TRUE);
Packit 8681c6
    key_obj = NULL;
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ec_hash_sign(STDLL_TokData_t *tokdata,
Packit 8681c6
                   SESSION *sess,
Packit 8681c6
                   CK_BBOOL length_only,
Packit 8681c6
                   SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
                   CK_BYTE *in_data,
Packit 8681c6
                   CK_ULONG in_data_len,
Packit 8681c6
                   CK_BYTE *signature, CK_ULONG *sig_len)
Packit 8681c6
{
Packit 8681c6
    CK_BYTE hash[MAX_SHA_HASH_SIZE];
Packit 8681c6
    DIGEST_CONTEXT digest_ctx;
Packit 8681c6
    SIGN_VERIFY_CONTEXT sign_ctx;
Packit 8681c6
    CK_MECHANISM digest_mech;
Packit 8681c6
    CK_MECHANISM sign_mech;
Packit 8681c6
    CK_ULONG hash_len;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (!sess || !ctx || !in_data) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
    memset(&digest_ctx, 0x0, sizeof(digest_ctx));
Packit 8681c6
    memset(&sign_ctx, 0x0, sizeof(sign_ctx));
Packit 8681c6
Packit 8681c6
    switch (ctx->mech.mechanism) {
Packit 8681c6
    case CKM_ECDSA_SHA1:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA_1;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA224:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA224;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA256:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA256;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA384:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA384;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA512:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA512;
Packit 8681c6
        break;
Packit 8681c6
    default:
Packit 8681c6
        return CKR_MECHANISM_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    digest_mech.ulParameterLen = 0;
Packit 8681c6
    digest_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
    rc = get_sha_size(digest_mech.mechanism, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Get SHA Size failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Init failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_digest(tokdata, sess, length_only, &digest_ctx, in_data,
Packit 8681c6
                           in_data_len, hash, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Digest failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    sign_mech.mechanism = CKM_ECDSA;
Packit 8681c6
    sign_mech.ulParameterLen = 0;
Packit 8681c6
    sign_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
    rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Sign Mgr Init failed.\n");
Packit 8681c6
        goto error;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = sign_mgr_sign(tokdata, sess, length_only, &sign_ctx, hash, hash_len,
Packit 8681c6
                       signature, sig_len);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        TRACE_DEVEL("Sign Mgr Sign failed.\n");
Packit 8681c6
Packit 8681c6
error:
Packit 8681c6
    sign_mgr_cleanup(&sign_ctx);
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ec_hash_sign_update(STDLL_TokData_t *tokdata,
Packit 8681c6
                          SESSION *sess,
Packit 8681c6
                          SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
                          CK_BYTE *in_data, CK_ULONG in_data_len)
Packit 8681c6
{
Packit 8681c6
    RSA_DIGEST_CONTEXT *context = NULL;
Packit 8681c6
    CK_MECHANISM digest_mech;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (!sess || !ctx) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
    context = (RSA_DIGEST_CONTEXT *) ctx->context;
Packit 8681c6
Packit 8681c6
    if (context->flag == FALSE) {
Packit 8681c6
        switch (ctx->mech.mechanism) {
Packit 8681c6
        case CKM_ECDSA_SHA1:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA_1;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA224:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA224;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA256:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA256;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA384:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA384;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA512:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA512;
Packit 8681c6
            break;
Packit 8681c6
        default:
Packit 8681c6
            return CKR_MECHANISM_INVALID;
Packit 8681c6
        }
Packit 8681c6
Packit 8681c6
        digest_mech.ulParameterLen = 0;
Packit 8681c6
        digest_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
        rc = digest_mgr_init(tokdata, sess, &context->hash_context,
Packit 8681c6
                             &digest_mech);
Packit 8681c6
        if (rc != CKR_OK) {
Packit 8681c6
            TRACE_DEVEL("Digest Mgr Init failed.\n");
Packit 8681c6
            return rc;
Packit 8681c6
        }
Packit 8681c6
        context->flag = TRUE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context,
Packit 8681c6
                                  in_data, in_data_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Update failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ec_hash_sign_final(STDLL_TokData_t *tokdata,
Packit 8681c6
                         SESSION *sess,
Packit 8681c6
                         CK_BBOOL length_only,
Packit 8681c6
                         SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
                         CK_BYTE *signature, CK_ULONG *sig_len)
Packit 8681c6
{
Packit 8681c6
    CK_BYTE hash[MAX_SHA_HASH_SIZE];
Packit 8681c6
    RSA_DIGEST_CONTEXT *context = NULL;
Packit 8681c6
    CK_ULONG hash_len;
Packit 8681c6
    CK_MECHANISM sign_mech;
Packit 8681c6
    SIGN_VERIFY_CONTEXT sign_ctx;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (!sess || !ctx || !sig_len) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    memset(&sign_ctx, 0x0, sizeof(sign_ctx));
Packit 8681c6
Packit 8681c6
    context = (RSA_DIGEST_CONTEXT *) ctx->context;
Packit 8681c6
Packit 8681c6
    rc = get_sha_size(context->hash_context.mech.mechanism, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Get SHA Size failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_digest_final(tokdata, sess, length_only,
Packit 8681c6
                                 &context->hash_context, hash, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Final failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    sign_mech.mechanism = CKM_ECDSA;
Packit 8681c6
    sign_mech.ulParameterLen = 0;
Packit 8681c6
    sign_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
    rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Sign Mgr Init failed.\n");
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
    //rc = sign_mgr_sign( sess, length_only, &sign_ctx, ber_data, ber_data_len,
Packit 8681c6
    //signature, sig_len );
Packit 8681c6
    rc = sign_mgr_sign(tokdata, sess, length_only, &sign_ctx, hash, hash_len,
Packit 8681c6
                       signature, sig_len);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        TRACE_DEVEL("Sign Mgr Sign failed.\n");
Packit 8681c6
Packit 8681c6
    if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) {
Packit 8681c6
        sign_mgr_cleanup(&sign_ctx);
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
done:
Packit 8681c6
    sign_mgr_cleanup(&sign_ctx);
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ec_hash_verify(STDLL_TokData_t *tokdata,
Packit 8681c6
                     SESSION *sess,
Packit 8681c6
                     SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
                     CK_BYTE *in_data,
Packit 8681c6
                     CK_ULONG in_data_len,
Packit 8681c6
                     CK_BYTE *signature, CK_ULONG sig_len)
Packit 8681c6
{
Packit 8681c6
    CK_BYTE hash[MAX_SHA_HASH_SIZE];
Packit 8681c6
    DIGEST_CONTEXT digest_ctx;
Packit 8681c6
    SIGN_VERIFY_CONTEXT verify_ctx;
Packit 8681c6
    CK_MECHANISM digest_mech;
Packit 8681c6
    CK_MECHANISM verify_mech;
Packit 8681c6
    CK_ULONG hash_len;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (!sess || !ctx || !in_data) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
    memset(&digest_ctx, 0x0, sizeof(digest_ctx));
Packit 8681c6
    memset(&verify_ctx, 0x0, sizeof(verify_ctx));
Packit 8681c6
Packit 8681c6
    switch (ctx->mech.mechanism) {
Packit 8681c6
    case CKM_ECDSA_SHA1:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA_1;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA224:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA224;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA256:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA256;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA384:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA384;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_ECDSA_SHA512:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA512;
Packit 8681c6
        break;
Packit 8681c6
    default:
Packit 8681c6
        return CKR_MECHANISM_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    digest_mech.ulParameterLen = 0;
Packit 8681c6
    digest_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
    rc = get_sha_size(digest_mech.mechanism, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Get SHA Size failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Init failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_digest(tokdata, sess, FALSE, &digest_ctx, in_data,
Packit 8681c6
                           in_data_len, hash, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Digest failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
    // Verify the Signed BER-encoded Data block
Packit 8681c6
    //
Packit 8681c6
    verify_mech.mechanism = CKM_ECDSA;
Packit 8681c6
    verify_mech.ulParameterLen = 0;
Packit 8681c6
    verify_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
    rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE,
Packit 8681c6
                         ctx->key);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Verify Mgr Init failed.\n");
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
    //rc = verify_mgr_verify( sess, &verify_ctx, ber_data, ber_data_len,
Packit 8681c6
    //signature, sig_len );
Packit 8681c6
    rc = verify_mgr_verify(tokdata, sess, &verify_ctx, hash, hash_len,
Packit 8681c6
                           signature, sig_len);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        TRACE_DEVEL("Verify Mgr Verify failed.\n");
Packit 8681c6
done:
Packit 8681c6
    sign_mgr_cleanup(&verify_ctx);
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
CK_RV ec_hash_verify_update(STDLL_TokData_t *tokdata,
Packit 8681c6
                            SESSION *sess,
Packit 8681c6
                            SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
                            CK_BYTE *in_data, CK_ULONG in_data_len)
Packit 8681c6
{
Packit 8681c6
    RSA_DIGEST_CONTEXT *context = NULL;
Packit 8681c6
    CK_MECHANISM digest_mech;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (!sess || !ctx) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
    context = (RSA_DIGEST_CONTEXT *) ctx->context;
Packit 8681c6
Packit 8681c6
    if (context->flag == FALSE) {
Packit 8681c6
        switch (ctx->mech.mechanism) {
Packit 8681c6
        case CKM_ECDSA_SHA1:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA_1;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA224:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA224;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA256:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA256;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA384:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA384;
Packit 8681c6
            break;
Packit 8681c6
        case CKM_ECDSA_SHA512:
Packit 8681c6
            digest_mech.mechanism = CKM_SHA512;
Packit 8681c6
            break;
Packit 8681c6
        default:
Packit 8681c6
            return CKR_MECHANISM_INVALID;
Packit 8681c6
        }
Packit 8681c6
Packit 8681c6
        digest_mech.ulParameterLen = 0;
Packit 8681c6
        digest_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
        rc = digest_mgr_init(tokdata, sess, &context->hash_context,
Packit 8681c6
                             &digest_mech);
Packit 8681c6
        if (rc != CKR_OK) {
Packit 8681c6
            TRACE_DEVEL("Digest Mgr Init failed.\n");
Packit 8681c6
            return rc;
Packit 8681c6
        }
Packit 8681c6
        context->flag = TRUE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context,
Packit 8681c6
                                  in_data, in_data_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Update failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ec_hash_verify_final(STDLL_TokData_t *tokdata,
Packit 8681c6
                           SESSION *sess,
Packit 8681c6
                           SIGN_VERIFY_CONTEXT *ctx,
Packit 8681c6
                           CK_BYTE *signature, CK_ULONG sig_len)
Packit 8681c6
{
Packit 8681c6
    CK_BYTE hash[MAX_SHA_HASH_SIZE];
Packit 8681c6
    RSA_DIGEST_CONTEXT *context = NULL;
Packit 8681c6
    CK_ULONG hash_len;
Packit 8681c6
    CK_MECHANISM verify_mech;
Packit 8681c6
    SIGN_VERIFY_CONTEXT verify_ctx;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
Packit 8681c6
    if (!sess || !ctx || !signature) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
    memset(&verify_ctx, 0x0, sizeof(verify_ctx));
Packit 8681c6
Packit 8681c6
    context = (RSA_DIGEST_CONTEXT *) ctx->context;
Packit 8681c6
Packit 8681c6
    rc = get_sha_size(context->hash_context.mech.mechanism, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Get SHA Size failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_digest_final(tokdata, sess, FALSE, &context->hash_context,
Packit 8681c6
                                 hash, &hash_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Digest Mgr Final failed.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
    verify_mech.mechanism = CKM_ECDSA;
Packit 8681c6
    verify_mech.ulParameterLen = 0;
Packit 8681c6
    verify_mech.pParameter = NULL;
Packit 8681c6
Packit 8681c6
    rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE,
Packit 8681c6
                         ctx->key);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_DEVEL("Verify Mgr Init failed.\n");
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = verify_mgr_verify(tokdata, sess, &verify_ctx, hash, hash_len,
Packit 8681c6
                           signature, sig_len);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        TRACE_DEVEL("Verify Mgr Verify failed.\n");
Packit 8681c6
done:
Packit 8681c6
    verify_mgr_cleanup(&verify_ctx);
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ckm_kdf(STDLL_TokData_t *tokdata, SESSION *sess, CK_ULONG kdf,
Packit 8681c6
              CK_BYTE *data, CK_ULONG data_len, CK_BYTE *hash, CK_ULONG *h_len)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;
Packit 8681c6
    DIGEST_CONTEXT ctx;
Packit 8681c6
    CK_MECHANISM digest_mech;
Packit 8681c6
Packit 8681c6
    memset(&ctx, 0, sizeof(DIGEST_CONTEXT));
Packit 8681c6
    memset(&digest_mech, 0, sizeof(CK_MECHANISM));
Packit 8681c6
Packit 8681c6
    switch (kdf) {
Packit 8681c6
    case CKD_SHA1_KDF:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA_1;
Packit 8681c6
        *h_len = SHA1_HASH_SIZE;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA224_KDF:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA224;
Packit 8681c6
        *h_len = SHA224_HASH_SIZE;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA256_KDF:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA256;
Packit 8681c6
        *h_len = SHA256_HASH_SIZE;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA384_KDF:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA384;
Packit 8681c6
        *h_len = SHA384_HASH_SIZE;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA512_KDF:
Packit 8681c6
        digest_mech.mechanism = CKM_SHA512;
Packit 8681c6
        *h_len = SHA512_HASH_SIZE;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_NULL:
Packit 8681c6
        memcpy(hash, data, data_len - 4);
Packit 8681c6
        *h_len = data_len - 4;  // data length minus counter length
Packit 8681c6
        return CKR_OK;
Packit 8681c6
    default:
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
Packit 8681c6
        return CKR_FUNCTION_NOT_SUPPORTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_init(tokdata, sess, &ctx, &digest_mech);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = digest_mgr_digest(tokdata, sess, FALSE, &ctx, data, data_len, hash,
Packit 8681c6
                           h_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("digest_mgr_digest failed with rc = %s\n", ock_err(rc));
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ckm_kdf_X9_63(STDLL_TokData_t *tokdata, SESSION *sess, CK_ULONG kdf,
Packit 8681c6
                    CK_ULONG kdf_digest_len, const CK_BYTE *z, CK_ULONG z_len,
Packit 8681c6
                    const CK_BYTE *shared_data, CK_ULONG shared_data_len,
Packit 8681c6
                    CK_BYTE *key, CK_ULONG key_len)
Packit 8681c6
{
Packit 8681c6
    CK_ULONG counter_length = 4;
Packit 8681c6
    CK_BYTE *ctx = NULL;
Packit 8681c6
    CK_ULONG ctx_len;
Packit 8681c6
    CK_BYTE hash[MAX_SUPPORTED_HASH_LENGTH];
Packit 8681c6
    CK_ULONG h_len;
Packit 8681c6
    CK_RV rc;
Packit Service 8aa27d
    unsigned int i, counter, counter_en;
Packit 8681c6
Packit 8681c6
    /* Check max keylen according to ANSI X9.63 */
Packit 8681c6
    /* digest_len * 2^32 */
Packit 8681c6
    CK_ULONG max_keybytes = kdf_digest_len * 0x100000000ul;
Packit 8681c6
    if (key_len >= max_keybytes) {
Packit 8681c6
        TRACE_ERROR("Desired key length %lu greater than max supported key "
Packit 8681c6
                    "length %lu.\n", key_len, max_keybytes);
Packit 8681c6
        return CKR_KEY_SIZE_RANGE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* If no KDF to be used, just return the shared_data.
Packit 8681c6
     * Cannot concatenate hashes. */
Packit 8681c6
    if (kdf == CKD_NULL) {
Packit 8681c6
        memcpy(key, z, z_len);
Packit 8681c6
        return CKR_OK;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Allocate memory for hash context */
Packit 8681c6
    ctx_len = z_len + counter_length + shared_data_len;
Packit 8681c6
    ctx = malloc(ctx_len);
Packit 8681c6
    if (!ctx)
Packit 8681c6
        return CKR_HOST_MEMORY;
Packit 8681c6
    memcpy(ctx, z, z_len);
Packit 8681c6
    if (shared_data_len > 0)
Packit 8681c6
        memcpy(ctx + z_len + counter_length, shared_data, shared_data_len);
Packit 8681c6
Packit 8681c6
    /* Provide key bytes according to ANSI X9.63 */
Packit 8681c6
    counter = 1;
Packit 8681c6
    for (i = 0; i < key_len / kdf_digest_len; i++) {
Packit Service 8aa27d
        counter_en = htobe32(counter);
Packit Service 8aa27d
        memcpy(ctx + z_len, &counter_en, counter_length);
Packit 8681c6
        rc = ckm_kdf(tokdata, sess, kdf, ctx, ctx_len, hash, &h_len);
Packit 8681c6
        if (rc != 0) {
Packit 8681c6
            free(ctx);
Packit 8681c6
            return rc;
Packit 8681c6
        }
Packit 8681c6
        memcpy(key + i * kdf_digest_len, hash, kdf_digest_len);
Packit 8681c6
        counter++;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    free(ctx);
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ckm_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, CK_VOID_PTR other_pubkey,
Packit 8681c6
                           CK_ULONG other_pubkey_len, CK_OBJECT_HANDLE base_key,
Packit 8681c6
                           CK_BYTE *secret_value, CK_ULONG *secret_value_len)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;
Packit 8681c6
    CK_ATTRIBUTE *attr;
Packit 8681c6
    OBJECT *base_key_obj = NULL;
Packit 8681c6
    CK_BYTE *oid_p;
Packit 8681c6
    CK_ULONG oid_len;
Packit 8681c6
Packit 8681c6
    if (token_specific.t_ecdh_pkcs_derive == NULL) {
Packit 8681c6
        TRACE_ERROR("ecdh pkcs derive is not supported by this token.\n");
Packit 8681c6
        return CKR_FUNCTION_NOT_SUPPORTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Find base_key struct */
Packit 8681c6
    rc = object_mgr_find_in_map1(tokdata, base_key, &base_key_obj, READ_LOCK);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Failed to acquire key from specified handle");
Packit 8681c6
        if (rc == CKR_OBJECT_HANDLE_INVALID)
Packit 8681c6
            return CKR_KEY_HANDLE_INVALID;
Packit 8681c6
        else
Packit 8681c6
            return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Get curve oid from CKA_ECDSA_PARAMS */
Packit 8681c6
    if (!template_attribute_find
Packit 8681c6
        (base_key_obj->template, CKA_ECDSA_PARAMS, &attr)) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
Packit 8681c6
        rc = CKR_TEMPLATE_INCOMPLETE;
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
    oid_p = attr->pValue;
Packit 8681c6
    oid_len = attr->ulValueLen;
Packit 8681c6
Packit 8681c6
    /* Extract EC private key (D) from base_key */
Packit 8681c6
    if (!template_attribute_find(base_key_obj->template, CKA_VALUE, &attr)) {
Packit 8681c6
        TRACE_ERROR("Could not find CKA_VALUE in the template\n");
Packit 8681c6
        rc = CKR_FUNCTION_FAILED;
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Call token specific ECDH key derivation function */
Packit 8681c6
    rc = token_specific.t_ecdh_pkcs_derive(tokdata,
Packit 8681c6
                                           (CK_BYTE *) (attr->pValue),
Packit 8681c6
                                           attr->ulValueLen,
Packit 8681c6
                                           (CK_BYTE *) other_pubkey,
Packit 8681c6
                                           other_pubkey_len, secret_value,
Packit 8681c6
                                           secret_value_len, oid_p, oid_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Token specific ecdh pkcs derive failed with rc=%ld.\n",
Packit 8681c6
                    rc);
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
done:
Packit 8681c6
    object_put(tokdata, base_key_obj, TRUE);
Packit 8681c6
    base_key_obj = NULL;
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
static CK_RV digest_from_kdf(CK_EC_KDF_TYPE kdf, CK_MECHANISM_TYPE *mech)
Packit 8681c6
{
Packit 8681c6
    switch (kdf) {
Packit 8681c6
    case CKD_SHA1_KDF:
Packit 8681c6
        *mech = CKM_SHA_1;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA224_KDF:
Packit 8681c6
        *mech = CKM_SHA224;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA256_KDF:
Packit 8681c6
        *mech = CKM_SHA256;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA384_KDF:
Packit 8681c6
        *mech = CKM_SHA384;
Packit 8681c6
        break;
Packit 8681c6
    case CKD_SHA512_KDF:
Packit 8681c6
        *mech = CKM_SHA512;
Packit 8681c6
        break;
Packit 8681c6
    default:
Packit 8681c6
        TRACE_ERROR("Error unsupported KDF %ld.\n", kdf);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV pkcs_get_keytype(CK_ATTRIBUTE *attrs, CK_ULONG attrs_len,
Packit 8681c6
                       CK_MECHANISM_PTR mech, CK_ULONG *type, CK_ULONG *class)
Packit 8681c6
{
Packit 8681c6
    CK_ULONG i;
Packit 8681c6
Packit 8681c6
    *type = 0;
Packit 8681c6
    *class = 0;
Packit 8681c6
Packit 8681c6
    for (i = 0; i < attrs_len; i++) {
Packit 8681c6
        if (attrs[i].type == CKA_CLASS) {
Packit 8681c6
            *class = *(CK_ULONG *) attrs[i].pValue;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    for (i = 0; i < attrs_len; i++) {
Packit 8681c6
        if (attrs[i].type == CKA_KEY_TYPE) {
Packit 8681c6
            *type = *(CK_ULONG *) attrs[i].pValue;
Packit 8681c6
            return CKR_OK;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* no CKA_KEY_TYPE found, derive from mech */
Packit 8681c6
    switch (mech->mechanism) {
Packit 8681c6
    case CKM_DES_KEY_GEN:
Packit 8681c6
        *type = CKK_DES;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_DES3_KEY_GEN:
Packit 8681c6
        *type = CKK_DES3;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_CDMF_KEY_GEN:
Packit 8681c6
        *type = CKK_CDMF;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_AES_KEY_GEN:
Packit 8681c6
        *type = CKK_AES;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_RSA_PKCS_KEY_PAIR_GEN:
Packit 8681c6
        *type = CKK_RSA;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_EC_KEY_PAIR_GEN:
Packit 8681c6
        *type = CKK_EC;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_DSA_KEY_PAIR_GEN:
Packit 8681c6
        *type = CKK_DSA;
Packit 8681c6
        break;
Packit 8681c6
    case CKM_DH_PKCS_KEY_PAIR_GEN:
Packit 8681c6
        *type = CKK_DH;
Packit 8681c6
        break;
Packit 8681c6
    default:
Packit 8681c6
        return CKR_MECHANISM_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
/**
Packit 8681c6
 * From PKCS#11 v2.40: PKCS #3 Diffie-Hellman key derivation
Packit 8681c6
 *
Packit 8681c6
 *   [...] It computes a Diffie-Hellman secret value from the public value and
Packit 8681c6
 *   private key according to PKCS #3, and truncates the result according to the
Packit 8681c6
 *   CKA_KEY_TYPE attribute of the template and, if it has one and the key type
Packit 8681c6
 *   supports it, the CKA_VALUE_LEN attribute of the template.
Packit 8681c6
 *
Packit 8681c6
 *   For some key types, the derived key length is known, for others it
Packit 8681c6
 *   must be specified in the template through CKA_VALUE_LEN.
Packit 8681c6
 *
Packit 8681c6
 */
Packit 8681c6
static CK_ULONG keylen_from_keytype(CK_ULONG keytype)
Packit 8681c6
{
Packit 8681c6
    switch (keytype) {
Packit 8681c6
    case CKK_DES:
Packit 8681c6
        return 8;
Packit 8681c6
    case CKK_DES2:
Packit 8681c6
        return 16;
Packit 8681c6
    case CKK_DES3:
Packit 8681c6
        return 24;
Packit 8681c6
        /* for all other keytypes CKA_VALUE_LEN must be specified */
Packit 8681c6
    default:
Packit 8681c6
        return 0;
Packit 8681c6
    }
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV ecdh_pkcs_derive(STDLL_TokData_t *tokdata, SESSION *sess,
Packit 8681c6
                       CK_MECHANISM *mech, CK_OBJECT_HANDLE base_key,
Packit 8681c6
                       CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount,
Packit 8681c6
                       CK_OBJECT_HANDLE *derived_key_obj)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;
Packit 8681c6
    CK_ULONG class = 0, keytype = 0, key_len = 0;
Packit 8681c6
    CK_ATTRIBUTE *new_attr;
Packit 8681c6
    OBJECT *temp_obj = NULL;
Packit 8681c6
    CK_ECDH1_DERIVE_PARAMS *pParms;
Packit 8681c6
    CK_BYTE z_value[MAX_ECDH_SHARED_SECRET_SIZE];
Packit 8681c6
    CK_ULONG z_len = 0, kdf_digest_len;
Packit 8681c6
    CK_MECHANISM_TYPE digest_mech;
Packit 8681c6
    CK_BYTE *derived_key = NULL;
Packit 8681c6
    CK_ULONG derived_key_len, i;
Packit 8681c6
Packit 8681c6
    /* Check parm length */
Packit 8681c6
    if (mech->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID));
Packit 8681c6
        return CKR_MECHANISM_PARAM_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Check buffers */
Packit 8681c6
    pParms = mech->pParameter;
Packit 8681c6
    if (pParms == NULL) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID));
Packit 8681c6
        return CKR_MECHANISM_PARAM_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (pParms->pPublicData == NULL) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID));
Packit 8681c6
        return CKR_MECHANISM_PARAM_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Get the keytype to use when deriving the key object */
Packit 8681c6
    rc = pkcs_get_keytype(pTemplate, ulCount, mech, &keytype, &class);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("get_keytype failed with rc=0x%lx\n", rc);
Packit Service 8aa27d
        return CKR_TEMPLATE_INCOMPLETE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Determine derived key length */
Packit 8681c6
    for (i = 0; i < ulCount; i++) {
Packit 8681c6
        if (pTemplate[i].type == CKA_VALUE_LEN) {
Packit 8681c6
            key_len = *(CK_ULONG *) pTemplate[i].pValue;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (key_len == 0) {
Packit 8681c6
        key_len = keylen_from_keytype(keytype);
Packit 8681c6
        if (key_len == 0) {
Packit 8681c6
            TRACE_ERROR("Derived key length not specified in template.\n");
Packit 8681c6
            return CKR_ATTRIBUTE_VALUE_INVALID;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Optional shared data can only be provided together with a KDF */
Packit 8681c6
    if (pParms->kdf == CKD_NULL
Packit 8681c6
        && (pParms->pSharedData != NULL || pParms->ulSharedDataLen != 0)) {
Packit 8681c6
        TRACE_ERROR("No KDF specified, but shared data ptr is not NULL.\n");
Packit 8681c6
        return CKR_ARGUMENTS_BAD;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Derive the shared secret */
Packit 8681c6
    rc = ckm_ecdh_pkcs_derive(tokdata, pParms->pPublicData,
Packit 8681c6
                              pParms->ulPublicDataLen, base_key, z_value,
Packit 8681c6
                              &z_len);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Error deriving the shared secret.\n");
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* If no KDF used, max possible key length is the shared_secret length */
Packit 8681c6
    if (pParms->kdf == CKD_NULL && key_len > z_len) {
Packit 8681c6
        TRACE_ERROR("Can only provide %ld key bytes without a KDF, "
Packit 8681c6
                    "but %ld bytes requested.\n",
Packit 8681c6
                    (pParms->ulPublicDataLen / 2), key_len);
Packit 8681c6
        return CKR_ARGUMENTS_BAD;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Determine digest length */
Packit 8681c6
    if (pParms->kdf != CKD_NULL) {
Packit 8681c6
        rc = digest_from_kdf(pParms->kdf, &digest_mech);
Packit 8681c6
        if (rc != CKR_OK) {
Packit 8681c6
            TRACE_ERROR("Cannot determine mech from kdf.\n");
Packit 8681c6
            return CKR_ARGUMENTS_BAD;
Packit 8681c6
        }
Packit 8681c6
        rc = get_sha_size(digest_mech, &kdf_digest_len);
Packit 8681c6
        if (rc != CKR_OK) {
Packit 8681c6
            TRACE_ERROR("Cannot determine SHA digest size.\n");
Packit 8681c6
            return CKR_ARGUMENTS_BAD;
Packit 8681c6
        }
Packit 8681c6
    } else {
Packit 8681c6
        kdf_digest_len = z_len;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Allocate memory for derived key */
Packit 8681c6
    derived_key_len = ((key_len / kdf_digest_len) + 1) * kdf_digest_len;
Packit 8681c6
    derived_key = malloc(derived_key_len);
Packit 8681c6
    if (!derived_key) {
Packit 8681c6
        TRACE_ERROR("Cannot allocate %lu bytes for derived key.\n",
Packit 8681c6
                    derived_key_len);
Packit 8681c6
        return CKR_HOST_MEMORY;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Apply KDF function to shared secret */
Packit 8681c6
    rc = ckm_kdf_X9_63(tokdata, sess, pParms->kdf, kdf_digest_len,
Packit 8681c6
                       z_value, z_len, pParms->pSharedData,
Packit 8681c6
                       pParms->ulSharedDataLen, derived_key, derived_key_len);
Packit 8681c6
    if (rc != CKR_OK)
Packit 8681c6
        goto end;
Packit 8681c6
Packit 8681c6
    /* Return the hashed and truncated derived bytes as CKA_VALUE attribute */
Packit 8681c6
    rc = build_attribute(CKA_VALUE, derived_key, key_len, &new_attr);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Failed to build the attribute from CKA_VALUE, rc=%s.\n",
Packit 8681c6
                    ock_err(rc));
Packit 8681c6
        goto end;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Create the object that will be passed back as a handle. This will contain
Packit 8681c6
     * the new (computed) value of the attribute. */
Packit 8681c6
    rc = object_mgr_create_skel(tokdata, sess, pTemplate, ulCount, MODE_KEYGEN,
Packit 8681c6
                                class, keytype, &temp_obj);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Object Mgr create skeleton failed, rc=%s.\n", ock_err(rc));
Packit 8681c6
        free(new_attr);
Packit 8681c6
        goto end;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Update the template in the object with the new attribute */
Packit 8681c6
    template_update_attribute(temp_obj->template, new_attr);
Packit 8681c6
Packit 8681c6
    /* At this point, the derived key is fully constructed...assign an object
Packit 8681c6
     * handle and store the key */
Packit 8681c6
    rc = object_mgr_create_final(tokdata, sess, temp_obj, derived_key_obj);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        TRACE_ERROR("Object Mgr create final failed, rc=%s.\n", ock_err(rc));
Packit 8681c6
        object_free(temp_obj);
Packit 8681c6
        temp_obj = NULL;
Packit 8681c6
        goto end;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    rc = CKR_OK;
Packit 8681c6
Packit 8681c6
end:
Packit 8681c6
    free(derived_key);
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
static int ec_nid_from_oid(CK_BYTE *oid, CK_ULONG oid_length)
Packit 8681c6
{
Packit 8681c6
    int i;
Packit 8681c6
Packit 8681c6
    for (i = 0; i < NUMEC; i++) {
Packit 8681c6
        if (der_ec_supported[i].data_size == oid_length &&
Packit 8681c6
            memcmp(der_ec_supported[i].data, oid, oid_length) == 0)
Packit 8681c6
            return der_ec_supported[i].nid;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return -1;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
static int ec_curve_type_from_oid(CK_BYTE *oid, CK_ULONG oid_length)
Packit 8681c6
{
Packit 8681c6
    int i;
Packit 8681c6
Packit 8681c6
    for (i = 0; i < NUMEC; i++) {
Packit 8681c6
        if (der_ec_supported[i].data_size == oid_length &&
Packit 8681c6
            memcmp(der_ec_supported[i].data, oid, oid_length) == 0)
Packit 8681c6
            return der_ec_supported[i].curve_type;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return -1;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
/*
Packit 8681c6
 * Uncompress a compressed EC public key. EC public keys can be un-compressed,
Packit 8681c6
 * compressed, or hybrid. The fist byte of an EC public key determines if it
Packit 8681c6
 * is compressed or not:
Packit 8681c6
 * POINT_CONVERSION_COMPRESSED = 0x02
Packit 8681c6
 * POINT_CONVERSION_UNCOMPRESSED = 0x04
Packit 8681c6
 * POINT_CONVERSION_HYBRID = 0x06
Packit 8681c6
 * Bit 0x01 determines if it is odd or even
Packit 8681c6
 * The out_pubkey buffer size must be at least 1+2*privkey_len.
Packit 8681c6
 */
Packit 8681c6
CK_RV ec_uncompress_public_key(CK_BYTE *curve, CK_ULONG curve_len,
Packit 8681c6
                               CK_BYTE *pubkey, CK_ULONG pubkey_len,
Packit 8681c6
                               CK_ULONG privkey_len,
Packit 8681c6
                               CK_BYTE *out_pubkey, CK_ULONG *out_len)
Packit 8681c6
{
Packit 8681c6
    EC_GROUP *group = NULL;
Packit 8681c6
    EC_POINT *point = NULL;
Packit 8681c6
    CK_ULONG pad_len = 0;
Packit 8681c6
    BIGNUM *bn_x = NULL;
Packit 8681c6
    BIGNUM *bn_y = NULL;
Packit 8681c6
    BN_CTX *ctx = NULL;
Packit 8681c6
    CK_RV rc;
Packit 8681c6
    int y_bit = 0;
Packit 8681c6
    CK_BYTE *x;
Packit 8681c6
    int nid, type;
Packit 8681c6
Packit 8681c6
    if (*out_len < 1 + 2 * privkey_len)
Packit 8681c6
        return CKR_BUFFER_TOO_SMALL;
Packit 8681c6
Packit 8681c6
    type = ec_curve_type_from_oid(curve, curve_len);
Packit 8681c6
    if (type == -1)
Packit 8681c6
        return CKR_CURVE_NOT_SUPPORTED;
Packit 8681c6
Packit 8681c6
    if (type == MONTGOMERY_CURVE || type == EDWARDS_CURVE) {
Packit 8681c6
        /*
Packit 8681c6
         * Public keys of Montgomery and Edwards curves are always compressed
Packit 8681c6
         * and are not uncompressed.
Packit 8681c6
         */
Packit 8681c6
        memcpy(out_pubkey, pubkey, pubkey_len);
Packit 8681c6
        *out_len = pubkey_len;
Packit 8681c6
        return CKR_OK;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    *out_len = 1 + 2 * privkey_len;
Packit 8681c6
Packit 8681c6
    if (pubkey_len == 1 + privkey_len &&
Packit 8681c6
        (pubkey[0] == POINT_CONVERSION_COMPRESSED ||
Packit 8681c6
         pubkey[0] == POINT_CONVERSION_COMPRESSED + 1)) {
Packit 8681c6
        /* Compressed form */
Packit 8681c6
        x = pubkey + 1;
Packit 8681c6
        y_bit = pubkey[0] & 0x01;
Packit 8681c6
    } else if (pubkey_len == 1 + 2 * privkey_len &&
Packit 8681c6
               pubkey[0] == POINT_CONVERSION_UNCOMPRESSED) {
Packit 8681c6
        /* Uncompressed form */
Packit 8681c6
        memcpy(out_pubkey, pubkey, pubkey_len);
Packit 8681c6
        return CKR_OK;
Packit 8681c6
    } else if (pubkey_len == 1 + 2 * privkey_len &&
Packit 8681c6
            (pubkey[0] == POINT_CONVERSION_HYBRID ||
Packit 8681c6
             pubkey[0] == POINT_CONVERSION_HYBRID + 1)) {
Packit 8681c6
        /* Hybrid form */
Packit 8681c6
        out_pubkey[0] = POINT_CONVERSION_UNCOMPRESSED;
Packit 8681c6
        memcpy(out_pubkey + 1, pubkey + 1, pubkey_len - 1);
Packit 8681c6
        return CKR_OK;
Packit 8681c6
    } else if (pubkey_len <= 2 * privkey_len) {
Packit 8681c6
        /* Without format byte (and leading zeros), treat as uncompressed */
Packit 8681c6
        pad_len = 2 * privkey_len - pubkey_len;
Packit 8681c6
        out_pubkey[0] = POINT_CONVERSION_UNCOMPRESSED;
Packit 8681c6
        memset(out_pubkey + 1, 0, pad_len);
Packit 8681c6
        memcpy(out_pubkey + 1 + pad_len, pubkey, pubkey_len);
Packit 8681c6
        return CKR_OK;
Packit 8681c6
    } else {
Packit 8681c6
        return CKR_KEY_SIZE_RANGE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    nid = ec_nid_from_oid(curve, curve_len);
Packit 8681c6
    if (nid == -1)
Packit 8681c6
        return CKR_CURVE_NOT_SUPPORTED;
Packit 8681c6
Packit 8681c6
    group = EC_GROUP_new_by_curve_name(nid);
Packit 8681c6
    if (group == NULL) {
Packit 8681c6
        TRACE_ERROR("Curve %d is not supported by openssl. Cannot decompress "
Packit 8681c6
                    "public key\n", nid);
Packit 8681c6
        return CKR_CURVE_NOT_SUPPORTED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    point = EC_POINT_new(group);
Packit 8681c6
    if (point == NULL) {
Packit 8681c6
        rc = CKR_FUNCTION_FAILED;
Packit 8681c6
        goto end;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    bn_x = BN_bin2bn(x, privkey_len, NULL);
Packit 8681c6
    bn_y = BN_new();
Packit 8681c6
    ctx = BN_CTX_new();
Packit 8681c6
Packit Service 8aa27d
    if (!EC_POINT_set_compressed_coordinates(group,
Packit Service 8aa27d
                                             point, bn_x, y_bit, ctx)) {
Packit 8681c6
        rc = CKR_FUNCTION_FAILED;
Packit 8681c6
        goto end;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (!EC_POINT_is_on_curve(group, point, ctx)) {
Packit 8681c6
        rc = CKR_FUNCTION_FAILED;
Packit 8681c6
        goto end;
Packit 8681c6
    }
Packit 8681c6
Packit Service 8aa27d
    if (!EC_POINT_get_affine_coordinates(group, point, bn_x, bn_y, ctx)) {
Packit 8681c6
        rc = CKR_FUNCTION_FAILED;
Packit 8681c6
        goto end;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    out_pubkey[0] = POINT_CONVERSION_UNCOMPRESSED;
Packit 8681c6
    memcpy(out_pubkey + 1, x, privkey_len);
Packit 8681c6
    BN_bn2binpad(bn_y, out_pubkey + 1 + privkey_len, privkey_len);
Packit 8681c6
    rc = CKR_OK;
Packit 8681c6
Packit 8681c6
end:
Packit 8681c6
    if (ctx)
Packit 8681c6
        BN_CTX_free(ctx);
Packit 8681c6
    if (point)
Packit 8681c6
        EC_POINT_free(point);
Packit 8681c6
    if (group)
Packit 8681c6
        EC_GROUP_free(group);
Packit 8681c6
    if (bn_x)
Packit 8681c6
        BN_free(bn_x);
Packit 8681c6
    if (bn_y)
Packit 8681c6
        BN_free(bn_y);
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}