Example #1
0
SECStatus
ectest_validate_point(ECDH_BAD *bad)
{
    ECParams ecParams = { 0 };
    SECItem point = { siBuffer, NULL, 0 };
    SECStatus rv = SECFailure;
    PLArenaPool *arena = NULL;

    rv = init_params(&ecParams, bad->curve, &arena, bad->fieldType);
    if (rv != SECSuccess) {
        return rv;
    }

    SECU_HexString2SECItem(arena, &point, bad->point);
    rv = EC_ValidatePublicKey(&ecParams, &point);

    PORT_FreeArena(arena, PR_FALSE);
    return rv;
}
Example #2
0
File: ec.c Project: txazo/hotspot
/*
** Performs an ECDH key derivation by computing the scalar point
** multiplication of privateValue and publicValue (with or without the
** cofactor) and returns the x-coordinate of the resulting elliptic
** curve point in derived secret.  If successful, derivedSecret->data
** is set to the address of the newly allocated buffer containing the
** derived secret, and derivedSecret->len is the size of the secret
** produced. It is the caller's responsibility to free the allocated
** buffer containing the derived secret.
*/
SECStatus
ECDH_Derive(SECItem  *publicValue,
            ECParams *ecParams,
            SECItem  *privateValue,
            PRBool    withCofactor,
            SECItem  *derivedSecret,
            int kmflag)
{
    SECStatus rv = SECFailure;
    unsigned int len = 0;
    SECItem pointQ = {siBuffer, NULL, 0};
    mp_int k; /* to hold the private value */
    mp_int cofactor;
    mp_err err = MP_OKAY;
#if EC_DEBUG
    int i;
#endif

    if (!publicValue || !ecParams || !privateValue ||
        !derivedSecret) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (EC_ValidatePublicKey(ecParams, publicValue, kmflag) != SECSuccess) {
        return SECFailure;
    }

    memset(derivedSecret, 0, sizeof *derivedSecret);
    len = (ecParams->fieldID.size + 7) >> 3;
    pointQ.len = 2*len + 1;
    if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;

    MP_DIGITS(&k) = 0;
    CHECK_MPI_OK( mp_init(&k, kmflag) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
                                          (mp_size) privateValue->len) );

    if (withCofactor && (ecParams->cofactor != 1)) {
            /* multiply k with the cofactor */
            MP_DIGITS(&cofactor) = 0;
            CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
            mp_set(&cofactor, ecParams->cofactor);
            CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
    }

    /* Multiply our private key and peer's public point */
    if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
        ec_point_at_infinity(&pointQ))
        goto cleanup;

    /* Allocate memory for the derived secret and copy
     * the x co-ordinate of pointQ into it.
     */
    SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
    memcpy(derivedSecret->data, pointQ.data + 1, len);

    rv = SECSuccess;

#if EC_DEBUG
    printf("derived_secret:\n");
    for (i = 0; i < derivedSecret->len; i++)
        printf("%02x:", derivedSecret->data[i]);
    printf("\n");
#endif

cleanup:
    mp_clear(&k);

    if (pointQ.data) {
        PORT_ZFree(pointQ.data, 2*len + 1);
    }

    return rv;
}
Example #3
0
SECStatus
ectest_ecdh_kat(ECDH_KAT *kat)
{
    ECCurveName curve = kat->curve;
    ECParams ecParams = { 0 };
    ECPrivateKey *ecPriv = NULL;
    SECItem theirKey = { siBuffer, NULL, 0 };
    SECStatus rv = SECFailure;
    PLArenaPool *arena = NULL;
    SECItem seed = { siBuffer, NULL, 0 };
    SECItem answer = { siBuffer, NULL, 0 };
    SECItem answer2 = { siBuffer, NULL, 0 };
    SECItem derived = { siBuffer, NULL, 0 };
    SECItem ecEncodedParams = { siBuffer, NULL, 0 };
    int i;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena) {
        return SECFailure;
    }

    rv = SECU_ecName2params(curve, &ecEncodedParams);
    if (rv != SECSuccess) {
        goto cleanup;
    }
    EC_FillParams(arena, &ecEncodedParams, &ecParams);

    if (kat->our_pubhex) {
        SECU_HexString2SECItem(arena, &answer, kat->our_pubhex);
    }
    SECU_HexString2SECItem(arena, &seed, kat->privhex);
    rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
    if (rv != SECSuccess) {
        rv = SECFailure;
        goto cleanup;
    }
    if (kat->our_pubhex) {
        if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
            rv = SECFailure;
            goto cleanup;
        }
    }

    SECU_HexString2SECItem(arena, &theirKey, kat->their_pubhex);
    SECU_HexString2SECItem(arena, &answer2, kat->common_key);

    rv = EC_ValidatePublicKey(&ecParams, &theirKey);
    if (rv != SECSuccess) {
        printf("EC_ValidatePublicKey failed\n");
        goto cleanup;
    }

    for (i = 0; i < kat->iterations; ++i) {
        rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
        if (rv != SECSuccess) {
            rv = SECFailure;
            goto cleanup;
        }
        rv = SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue);
        if (rv != SECSuccess) {
            goto cleanup;
        }
        rv = SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived);
        if (rv != SECSuccess) {
            goto cleanup;
        }
        SECITEM_FreeItem(&derived, PR_FALSE);
    }

    if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) {
        printf("expected: ");
        printBuf(&answer2);
        printf("derived:  ");
        printBuf(&ecPriv->privateValue);
        rv = SECFailure;
        goto cleanup;
    }

cleanup:
    SECITEM_FreeItem(&ecEncodedParams, PR_FALSE);
    PORT_FreeArena(arena, PR_FALSE);
    if (ecPriv) {
        PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
    }
    if (derived.data) {
        SECITEM_FreeItem(&derived, PR_FALSE);
    }
    return rv;
}
static int
fips_ecdsa_sign_verify(uint8_t *encodedParams,
                       unsigned int encodedParamsLen,
                       uint8_t *knownSignature,
                       unsigned int knownSignatureLen) {

    /* ECDSA Known Seed info for curves nistp256 */
    static uint8_t ecdsa_Known_Seed[] = {
        0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11,
        0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1,
        0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc,
        0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f
    };

    static uint8_t msg[] = {
        "Sun Microsystems Solaris is awesome!"
    };

    unsigned char sha1[SHA1_DIGEST_SIZE];  /* SHA-1 hash (160 bits) */
    unsigned char sig[2*MAX_ECKEY_LEN];
    SECItem signature, digest;
    SECItem encodedparams;
    ECParams *ecparams = NULL;
    ECPrivateKey *ecdsa_private_key = NULL;
    ECPublicKey ecdsa_public_key;
    SECStatus ecdsaStatus = SECSuccess;
    SHA1_CTX *sha1_context = NULL;
    int rv = CKR_DEVICE_ERROR;

    (void) memset(&ecdsa_public_key, 0, sizeof (ECPublicKey));
    /* construct the ECDSA private/public key pair */
    encodedparams.type = siBuffer;
    encodedparams.data = (unsigned char *) encodedParams;
    encodedparams.len = encodedParamsLen;

    if (EC_DecodeParams(&encodedparams, &ecparams, 0) != SECSuccess) {
        return (CKR_ARGUMENTS_BAD);
    }

    /*
     * Generates a new EC key pair. The private key is a supplied
     * random value (in seed) and the public key is the result of
     * performing a scalar point multiplication of that value with
     * the curve's base point.
     */

    ecdsaStatus = ec_NewKey(ecparams, &ecdsa_private_key,
                            ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0);

    if (ecdsaStatus != SECSuccess) {
        goto loser;
    }

    /* construct public key from private key. */
    ecdsaStatus = EC_CopyParams(ecdsa_private_key->ecParams.arena,
                                &ecdsa_public_key.ecParams, &ecdsa_private_key->ecParams);

    if (ecdsaStatus != SECSuccess) {
        goto loser;
    }

    ecdsa_public_key.publicValue = ecdsa_private_key->publicValue;

    /* validate public key value */
    ecdsaStatus = EC_ValidatePublicKey(&ecdsa_public_key.ecParams,
                                       &ecdsa_public_key.publicValue, 0);

    if (ecdsaStatus != SECSuccess) {
        goto loser;
    }

    /* validate public key value */
    ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key->ecParams,
                                       &ecdsa_private_key->publicValue, 0);

    if (ecdsaStatus != SECSuccess) {
        goto loser;
    }

    /*
     * ECDSA Known Answer Signature Test.
     */
#ifdef _KERNEL
    if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX),
                                    KM_SLEEP)) == NULL) {
#else
    if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL) {
#endif
        ecdsaStatus = SECFailure;
        rv = CKR_HOST_MEMORY;
        goto loser;
    }

    SHA1Init(sha1_context);

#ifdef	__sparcv9
    SHA1Update(sha1_context, msg, (uint_t)sizeof (msg));
#else	/* !__sparcv9 */
    SHA1Update(sha1_context, msg, sizeof (msg));
#endif	/* __sparcv9 */
    SHA1Final(sha1, sha1_context);

    digest.type = siBuffer;
    digest.data = sha1;
    digest.len = SHA1_DIGEST_SIZE;

    (void) memset(sig, 0, sizeof (sig));
    signature.type = siBuffer;
    signature.data = sig;
    signature.len = sizeof (sig);

    ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature,
                                           &digest, ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0);

    if (ecdsaStatus != SECSuccess) {
        goto loser;
    }

    if ((signature.len != knownSignatureLen) ||
            (memcmp(signature.data, knownSignature,
                    knownSignatureLen) != 0)) {
        ecdsaStatus = SECFailure;
        goto loser;
    }

    /*
     * ECDSA Known Answer Verification Test.
     */
    ecdsaStatus = ECDSA_VerifyDigest(&ecdsa_public_key, &signature,
                                     &digest, 0);

loser:
    if (ecdsa_public_key.publicValue.data != NULL)
        free_ecpubkey(&ecdsa_public_key);
    if (ecdsa_private_key != NULL)
        free_ecprivkey(ecdsa_private_key);
    free_ecparams(ecparams, B_TRUE);

    if (sha1_context != NULL)
#ifdef _KERNEL
        kmem_free(sha1_context, sizeof (SHA1_CTX));
#else
        free(sha1_context);
#endif

    if (ecdsaStatus != SECSuccess) {
        return (rv);
    }

    return (CKR_OK);
}

int
fips_ecdsa_post() {

    /* ECDSA Known curve nistp256 == SEC_OID_SECG_EC_SECP256R1 params */
    static uint8_t ecdsa_known_P256_EncodedParams[] = {
        0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
        0x01, 0x07
    };

    static uint8_t ecdsa_known_P256_signature[] = {
        0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6,
        0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
        0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
        0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
        0x2b, 0xdb, 0x86, 0x76, 0xe7, 0x32, 0xba, 0x13,
        0x03, 0x7f, 0x7f, 0x92, 0x77, 0xd8, 0x35, 0xfe,
        0x99, 0xb4, 0xb7, 0x85, 0x5a, 0xfb, 0xfb, 0xce,
        0x5d, 0x0e, 0xbc, 0x01, 0xfa, 0x44, 0x97, 0x7e
    };

    int rv;

    /* ECDSA GF(p) prime field curve test */
    rv = fips_ecdsa_sign_verify(ecdsa_known_P256_EncodedParams,
                                sizeof (ecdsa_known_P256_EncodedParams),
                                ecdsa_known_P256_signature,
                                sizeof (ecdsa_known_P256_signature));

    if (rv != CKR_OK) {
        return (CKR_DEVICE_ERROR);
    }

    return (CKR_OK);
}

static void
free_ecparams(ECParams *params, boolean_t freeit)
{
    SECITEM_FreeItem(&params->fieldID.u.prime, B_FALSE);
    SECITEM_FreeItem(&params->curve.a, B_FALSE);
    SECITEM_FreeItem(&params->curve.b, B_FALSE);
    SECITEM_FreeItem(&params->curve.seed, B_FALSE);
    SECITEM_FreeItem(&params->base, B_FALSE);
    SECITEM_FreeItem(&params->order, B_FALSE);
    SECITEM_FreeItem(&params->DEREncoding, B_FALSE);
    SECITEM_FreeItem(&params->curveOID, B_FALSE);
    if (freeit)
#ifdef _KERNEL
        kmem_free(params, sizeof (ECParams));
#else
        free(params);
#endif
}