OP-TEE / optee_os

Trusted side of the TEE
Other
1.59k stars 1.07k forks source link

Issue with PKCS11 EDCSA SHA 384 key size #5797

Closed PrithviAPai closed 1 year ago

PrithviAPai commented 1 year ago

Hi Team,

I m trying to generate EDCSA key pairs using PKCS11 APIs. Once key pairs are generated I fetch the public key and private key using TEE_GetObjectBufferAttribute as per the spec. But when I see the length of the private it happens to be 48 bytes and on the other hand public key length(obtained by adding X component and Y component ) happens to be 96 bytes. Is there anything I m missing here ?

As per expectation private key len should be 192 bytes and public key length should be 192 bytes.

Please help me.

Thanks

jforissier commented 1 year ago

Hello @PrithviAPai,

Could you share some code to illustrate the issue?

PrithviAPai commented 1 year ago
TEE_Result TA_GetTEEData(TEE_ObjectHandle tee_obj,
                        uint32_t attribute,
                        void **data, size_t *size)
{
    TEE_Result res = TEE_ERROR_GENERIC;
    void *ptr = NULL;
    uint32_t sz = 0;

    res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
    if (res != TEE_ERROR_SHORT_BUFFER)
        return TEE_ERROR_GENERIC;

    ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
    if (!ptr)
        return TEE_ERROR_GENERIC;

    res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
    if (res) {
        TEE_Free(ptr);
    } else {
        *data = ptr;
        *size = sz;
    }
    return res;
}

TEE_Result TA_GetKeyValues(TEE_ObjectHandle tee_obj, void **private_key, void **public_key, size_t *priv_len, size_t *pub_len)
{
    TEE_Result res = TEE_ERROR_GENERIC;
    void *x_ptr = NULL;
    void *y_ptr = NULL;
    size_t x_size = 0;
    size_t y_size = 0;
    void *ecpoint = NULL;

    res = TA_GetTEEData(tee_obj, TEE_ATTR_ECC_PRIVATE_VALUE, private_key, priv_len);
    if (res)
        goto out;
    res = TA_GetTEEData(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_X, &x_ptr, &x_size);
    if (res)
        goto out;
    res = TA_GetTEEData(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_Y, &y_ptr, &y_size);
    if (res)
        goto out;
    ecpoint = TEE_Malloc(x_size + y_size, TEE_MALLOC_FILL_ZERO);
    if (!ecpoint) {
        res = TEE_ERROR_GENERIC;
        TEE_Free(x_ptr);
        TEE_Free(y_ptr);
        goto out;
    }
    TEE_MemMove(ecpoint, x_ptr, x_size);
    TEE_MemMove(ecpoint+x_size, y_ptr, y_size);
    public_key = ecpoint;
    *pub_len = x_size + y_size;
    goto out;
out:
    return res;
}

TEE_Result TA_GenerateECDSAKeys(key_pair_storage *state, uint32_t pt,
                  __maybe_unused TEE_Param params[TEE_NUM_PARAMS])
{
    TEE_Result res;
    uint32_t key_size;
    TEE_Attribute tee_key_attr[1] = { };
    TEE_ObjectHandle root_key = TEE_HANDLE_NULL;
    size_t priv_len = 0, pub_len = 0;
    size_t n;

    TEE_FreeTransientObject(state->root_key_pair);

    const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
                        TEE_PARAM_TYPE_MEMREF_OUTPUT,
                        TEE_PARAM_TYPE_NONE,
                        TEE_PARAM_TYPE_NONE);

    if (pt != exp_pt)
        return TEE_ERROR_BAD_PARAMETERS;

    key_size = 384;

    TEE_InitValueAttribute(tee_key_attr, TEE_ATTR_ECC_CURVE, TEE_ECC_CURVE_NIST_P384, 0);

    /* Create an ECDSA TEE key: will match PKCS11 ECDSA and ECDH */
    res = TEE_AllocateTransientObject(TEE_TYPE_ECDSA_KEYPAIR, key_size,
                      &root_key);
    if (res) {
        EMSG("TEE_GenerateKey(%" PRId32 "): %#" PRIx32,
             key_size, res);
        TEE_FreeTransientObject(root_key);
        return res;
    }
    res = TEE_RestrictObjectUsage1(root_key, TEE_USAGE_EXTRACTABLE);
    if (res) {
        EMSG("TEE_GenerateKey(%" PRId32 "): %#" PRIx32,
             key_size, res);
        TEE_FreeTransientObject(root_key);
        return res;
    }
    res = TEE_GenerateKey(root_key, key_size, tee_key_attr, 1);
    if (res) {
        EMSG("TEE_GenerateKey(%" PRId32 "): %#" PRIx32,
             key_size, res);
        TEE_FreeTransientObject(root_key);
        return res;
    }

    res = TA_GetKeyValues(root_key, &state->root_private_key, &state->root_public_key, &priv_len, &pub_len);
    if (res) {
        EMSG("TEE_GenerateKey(%" PRId32 "): %#" PRIx32,
             key_size, res);
        TEE_FreeTransientObject(root_key);
        return res;
    }
    state->root_key_pair = root_key;
    EMSG("\n private key_size: 0x%x\n ", priv_len);
    EMSG("\n public key_size: 0x%x\n ", pub_len);
    return TEE_SUCCESS;
}
PrithviAPai commented 1 year ago

@jforissier please check and help me out in case if I m missing something

jforissier commented 1 year ago

You are using TEE_ECC_CURVE_NIST_P384 so it looks reasonable to me that p, x and y are all 48 bytes (= 384 bits).

PrithviAPai commented 1 year ago

Thanks a lot @jforissier I have a follow up question, does OP-TEE support creation of self signed certificate ? I m very sorry I m new to this area. If you have any examples it would be very helpful

jforissier commented 1 year ago

You can probably do it with MBed TLS but I must say I don't know how exactly.

PrithviAPai commented 1 year ago

Thanks a lot @jforissier Is it okay to create keys via PKCS and use crypto to generate certificates, verify certificate chain and sign the hash ?