Exemple #1
0
/*
 * Class:     sun_security_ec_ECKeyPairGenerator
 * Method:    generateECKeyPair
 * Signature: (I[B[B)[[B
 */
JNIEXPORT jobjectArray
JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
  (JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)
{
    ECPrivateKey *privKey = NULL; // contains both public and private values
    ECParams *ecparams = NULL;
    SECKEYECParams params_item;
    jint jSeedLength;
    jbyte* pSeedBuffer = NULL;
    jobjectArray result = NULL;
    jclass baCls = NULL;
    jbyteArray jba;

    // Initialize the ECParams struct
    params_item.len = env->GetArrayLength(encodedParams);
    params_item.data =
        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    if (params_item.data == NULL) {
        goto cleanup;
    }

    // Fill a new ECParams using the supplied OID
    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
        /* bad curve OID */
        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
        goto cleanup;
    }

    // Copy seed from Java to native buffer
    jSeedLength = env->GetArrayLength(seed);
    pSeedBuffer = new jbyte[jSeedLength];
    env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);

    // Generate the new keypair (using the supplied seed)
    if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer,
        jSeedLength, 0) != SECSuccess) {
        ThrowException(env, KEY_EXCEPTION);
        goto cleanup;
    }

    jboolean isCopy;
    baCls = env->FindClass("[B");
    if (baCls == NULL) {
        goto cleanup;
    }
    result = env->NewObjectArray(2, baCls, NULL);
    if (result == NULL) {
        goto cleanup;
    }
    jba = getEncodedBytes(env, &(privKey->privateValue));
    if (jba == NULL) {
        result = NULL;
        goto cleanup;
    }
    env->SetObjectArrayElement(result, 0, jba); // big integer
    if (env->ExceptionCheck()) { // should never happen
        result = NULL;
        goto cleanup;
    }

    jba = getEncodedBytes(env, &(privKey->publicValue));
    if (jba == NULL) {
        result = NULL;
        goto cleanup;
    }
    env->SetObjectArrayElement(result, 1, jba); // encoded ec point
    if (env->ExceptionCheck()) { // should never happen
        result = NULL;
        goto cleanup;
    }

cleanup:
    {
        if (params_item.data) {
            env->ReleaseByteArrayElements(encodedParams,
                (jbyte *) params_item.data, JNI_ABORT);
        }
        if (ecparams) {
            FreeECParams(ecparams, true);
        }
        if (privKey) {
            FreeECParams(&privKey->ecParams, false);
            SECITEM_FreeItem(&privKey->version, B_FALSE);
            SECITEM_FreeItem(&privKey->privateValue, B_FALSE);
            SECITEM_FreeItem(&privKey->publicValue, B_FALSE);
            free(privKey);
        }

        if (pSeedBuffer) {
            delete [] pSeedBuffer;
        }
    }

    return result;
}
Exemple #2
0
/*
 * Class:     sun_security_ec_ECDHKeyAgreement
 * Method:    deriveKey
 * Signature: ([B[B[B)[B
 */
JNIEXPORT jbyteArray
JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
  (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams)
{
    jbyteArray jSecret = NULL;
    ECParams *ecparams = NULL;
    SECItem privateValue_item;
    privateValue_item.data = NULL;
    SECItem publicValue_item;
    publicValue_item.data = NULL;
    SECKEYECParams params_item;
    params_item.data = NULL;

    // Extract private key value
    privateValue_item.len = env->GetArrayLength(privateKey);
    privateValue_item.data =
            (unsigned char *) env->GetByteArrayElements(privateKey, 0);
    if (privateValue_item.data == NULL) {
        goto cleanup;
    }

    // Extract public key value
    publicValue_item.len = env->GetArrayLength(publicKey);
    publicValue_item.data =
        (unsigned char *) env->GetByteArrayElements(publicKey, 0);
    if (publicValue_item.data == NULL) {
        goto cleanup;
    }

    // Initialize the ECParams struct
    params_item.len = env->GetArrayLength(encodedParams);
    params_item.data =
        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    if (params_item.data == NULL) {
        goto cleanup;
    }

    // Fill a new ECParams using the supplied OID
    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
        /* bad curve OID */
        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
        goto cleanup;
    }

    // Prepare a buffer for the secret
    SECItem secret_item;
    secret_item.data = NULL;
    secret_item.len = ecparams->order.len * 2;

    if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE,
        &secret_item, 0) != SECSuccess) {
        ThrowException(env, ILLEGAL_STATE_EXCEPTION);
        goto cleanup;
    }

    // Create new byte array
    jSecret = env->NewByteArray(secret_item.len);
    if (jSecret == NULL) {
        goto cleanup;
    }

    // Copy bytes from the SECItem buffer to a Java byte array
    env->SetByteArrayRegion(jSecret, 0, secret_item.len,
        (jbyte *)secret_item.data);

    // Free the SECItem data buffer
    SECITEM_FreeItem(&secret_item, B_FALSE);

cleanup:
    {
        if (privateValue_item.data)
            env->ReleaseByteArrayElements(privateKey,
                (jbyte *) privateValue_item.data, JNI_ABORT);

        if (publicValue_item.data)
            env->ReleaseByteArrayElements(publicKey,
                (jbyte *) publicValue_item.data, JNI_ABORT);

        if (params_item.data)
            env->ReleaseByteArrayElements(encodedParams,
                (jbyte *) params_item.data, JNI_ABORT);

        if (ecparams)
            FreeECParams(ecparams, true);
    }

    return jSecret;
}
Exemple #3
0
/*
 * Class:     sun_security_ec_ECDSASignature
 * Method:    signDigest
 * Signature: ([B[B[B[B)[B
 */
JNIEXPORT jbyteArray
JNICALL Java_sun_security_ec_ECDSASignature_signDigest
  (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed)
{
    jbyte* pDigestBuffer = NULL;
    jint jDigestLength = env->GetArrayLength(digest);
    jbyteArray jSignedDigest = NULL;

    SECItem signature_item;
    jbyte* pSignedDigestBuffer = NULL;
    jbyteArray temp;

    jint jSeedLength = env->GetArrayLength(seed);
    jbyte* pSeedBuffer = NULL;

    // Copy digest from Java to native buffer
    pDigestBuffer = new jbyte[jDigestLength];
    env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
    SECItem digest_item;
    digest_item.data = (unsigned char *) pDigestBuffer;
    digest_item.len = jDigestLength;

    ECPrivateKey privKey;
    privKey.privateValue.data = NULL;

    // Initialize the ECParams struct
    ECParams *ecparams = NULL;
    SECKEYECParams params_item;
    params_item.len = env->GetArrayLength(encodedParams);
    params_item.data =
        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    if (params_item.data == NULL) {
        goto cleanup;
    }

    // Fill a new ECParams using the supplied OID
    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
        /* bad curve OID */
        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
        goto cleanup;
    }

    // Extract private key data
    privKey.ecParams = *ecparams; // struct assignment
    privKey.privateValue.len = env->GetArrayLength(privateKey);
    privKey.privateValue.data =
        (unsigned char *) env->GetByteArrayElements(privateKey, 0);
    if (privKey.privateValue.data == NULL) {
        goto cleanup;
    }

    // Prepare a buffer for the signature (twice the key length)
    pSignedDigestBuffer = new jbyte[ecparams->order.len * 2];
    signature_item.data = (unsigned char *) pSignedDigestBuffer;
    signature_item.len = ecparams->order.len * 2;

    // Copy seed from Java to native buffer
    pSeedBuffer = new jbyte[jSeedLength];
    env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);

    // Sign the digest (using the supplied seed)
    if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,
        (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) {
        ThrowException(env, KEY_EXCEPTION);
        goto cleanup;
    }

    // Create new byte array
    temp = env->NewByteArray(signature_item.len);
    if (temp == NULL) {
        goto cleanup;
    }

    // Copy data from native buffer
    env->SetByteArrayRegion(temp, 0, signature_item.len, pSignedDigestBuffer);
    jSignedDigest = temp;

cleanup:
    {
        if (params_item.data) {
            env->ReleaseByteArrayElements(encodedParams,
                (jbyte *) params_item.data, JNI_ABORT);
        }
        if (privKey.privateValue.data) {
            env->ReleaseByteArrayElements(privateKey,
                (jbyte *) privKey.privateValue.data, JNI_ABORT);
        }
        if (pDigestBuffer) {
            delete [] pDigestBuffer;
        }
        if (pSignedDigestBuffer) {
            delete [] pSignedDigestBuffer;
        }
        if (pSeedBuffer) {
            delete [] pSeedBuffer;
        }
        if (ecparams) {
            FreeECParams(ecparams, true);
        }
    }

    return jSignedDigest;
}
Exemple #4
0
/*
 * Class:     sun_security_ec_ECDSASignature
 * Method:    verifySignedDigest
 * Signature: ([B[B[B[B)Z
 */
JNIEXPORT jboolean
JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest
  (JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams)
{
    jboolean isValid = false;

    // Copy signedDigest from Java to native buffer
    jbyte* pSignedDigestBuffer = NULL;
    jint jSignedDigestLength = env->GetArrayLength(signedDigest);
    pSignedDigestBuffer = new jbyte[jSignedDigestLength];
    env->GetByteArrayRegion(signedDigest, 0, jSignedDigestLength,
        pSignedDigestBuffer);
    SECItem signature_item;
    signature_item.data = (unsigned char *) pSignedDigestBuffer;
    signature_item.len = jSignedDigestLength;

    // Copy digest from Java to native buffer
    jbyte* pDigestBuffer = NULL;
    jint jDigestLength = env->GetArrayLength(digest);
    pDigestBuffer = new jbyte[jDigestLength];
    env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
    SECItem digest_item;
    digest_item.data = (unsigned char *) pDigestBuffer;
    digest_item.len = jDigestLength;

    // Extract public key data
    ECPublicKey pubKey;
    pubKey.publicValue.data = NULL;
    ECParams *ecparams = NULL;
    SECKEYECParams params_item;

    // Initialize the ECParams struct
    params_item.len = env->GetArrayLength(encodedParams);
    params_item.data =
        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    if (params_item.data == NULL) {
        goto cleanup;
    }

    // Fill a new ECParams using the supplied OID
    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
        /* bad curve OID */
        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
        goto cleanup;
    }
    pubKey.ecParams = *ecparams; // struct assignment
    pubKey.publicValue.len = env->GetArrayLength(publicKey);
    pubKey.publicValue.data =
        (unsigned char *) env->GetByteArrayElements(publicKey, 0);

    if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0)
            != SECSuccess) {
        goto cleanup;
    }

    isValid = true;

cleanup:
    {
        if (params_item.data)
            env->ReleaseByteArrayElements(encodedParams,
                (jbyte *) params_item.data, JNI_ABORT);

        if (pubKey.publicValue.data)
            env->ReleaseByteArrayElements(publicKey,
                (jbyte *) pubKey.publicValue.data, JNI_ABORT);

        if (ecparams)
            FreeECParams(ecparams, true);

        if (pSignedDigestBuffer)
            delete [] pSignedDigestBuffer;

        if (pDigestBuffer)
            delete [] pDigestBuffer;
    }

    return isValid;
}
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
}