Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ec.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif

#include "blapi.h"
#include "blapii.h"
#include "prerr.h"
#include "secerr.h"
#include "secmpi.h"
#include "secitem.h"
#include "mplogic.h"
#include "ec.h"
#include "ecl.h"
#include "verified/Hacl_P384.h"
#include "verified/Hacl_P521.h"
#include "secport.h"
#include "verified/Hacl_Ed25519.h"

#define EC_DOUBLECHECK PR_FALSE

SECStatus
ec_ED25519_pt_validate(const SECItem *px)
{
    if (!px || !px->data || px->len != Ed25519_PUBLIC_KEYLEN) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    return SECSuccess;
}

SECStatus
ec_ED25519_scalar_validate(const SECItem *scalar)
{
    if (!scalar || !scalar->data || scalar->len != Ed25519_PRIVATE_KEYLEN) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    return SECSuccess;
}

static const ECMethod kMethods[] = {
    { ECCurve25519,
      ec_Curve25519_pt_mul,
      ec_Curve25519_pt_validate,
      ec_Curve25519_scalar_validate,
      NULL,
      NULL },
    {
        ECCurve_NIST_P256,
        ec_secp256r1_pt_mul,
        ec_secp256r1_pt_validate,
        ec_secp256r1_scalar_validate,
        ec_secp256r1_sign_digest,
        ec_secp256r1_verify_digest,
    },
    {
        ECCurve_NIST_P384,
        ec_secp384r1_pt_mul,
        ec_secp384r1_pt_validate,
        ec_secp384r1_scalar_validate,
        ec_secp384r1_sign_digest,
        ec_secp384r1_verify_digest,
    },
    {
        ECCurve_NIST_P521,
        ec_secp521r1_pt_mul,
        ec_secp521r1_pt_validate,
        ec_secp521r1_scalar_validate,
        ec_secp521r1_sign_digest,
        ec_secp521r1_verify_digest,
    },
    { ECCurve_Ed25519,
      NULL,
      ec_ED25519_pt_validate,
      ec_ED25519_scalar_validate,
      NULL,
      NULL },
};

static const ECMethod *
ec_get_method_from_name(ECCurveName name)
{
    unsigned long i;
    for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
        if (kMethods[i].name == name) {
            return &kMethods[i];
        }
    }
    return NULL;
}

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

SECStatus
ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
          const unsigned char *privKeyBytes, int privKeyLen)
{
    SECStatus rv = SECFailure;
    PLArenaPool *arena;
    ECPrivateKey *key;
    int len;

    if (!ecParams || ecParams->name == ECCurve_noName ||
        !privKey || !privKeyBytes || privKeyLen <= 0) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (ecParams->fieldID.type != ec_field_plain) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    /* Initialize an arena for the EC key. */
    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
        return SECFailure;

    key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
    if (!key) {
        goto cleanup;
    }

    /* Set the version number (SEC 1 section C.4 says it should be 1) */
    SECITEM_AllocItem(arena, &key->version, 1);
    key->version.data[0] = 1;

    /* Copy all of the fields from the ECParams argument to the
     * ECParams structure within the private key.
     */

    key->ecParams.arena = arena;
    key->ecParams.type = ecParams->type;
    key->ecParams.fieldID.size = ecParams->fieldID.size;
    key->ecParams.fieldID.type = ecParams->fieldID.type;
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
                                  &ecParams->fieldID.u.prime));
    key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
    key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
    key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
                                  &ecParams->curve.a));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
                                  &ecParams->curve.b));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
                                  &ecParams->curve.seed));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
                                  &ecParams->base));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
                                  &ecParams->order));
    key->ecParams.cofactor = ecParams->cofactor;
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
                                  &ecParams->DEREncoding));
    key->ecParams.name = ecParams->name;
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
                                  &ecParams->curveOID));

    SECITEM_AllocItem(arena, &key->publicValue, EC_GetPointSize(ecParams));
    len = ecParams->order.len;
    SECITEM_AllocItem(arena, &key->privateValue, len);

    /* Copy private key */
    if (privKeyLen >= len) {
        memcpy(key->privateValue.data, privKeyBytes, len);
    } else {
        memset(key->privateValue.data, 0, (len - privKeyLen));
        memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
    }

    /* Compute corresponding public key */

    /* Use curve specific code for point multiplication */
    if (ecParams->name == ECCurve_Ed25519) {
        CHECK_SEC_OK(ED_DerivePublicKey(&key->privateValue, &key->publicValue));
    } else {
        const ECMethod *method = ec_get_method_from_name(ecParams->name);
        if (method == NULL || method->pt_mul == NULL) {
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
            rv = SECFailure;
            goto cleanup;
        }
        CHECK_SEC_OK(method->pt_mul(&key->publicValue, &key->privateValue, NULL));
    }

    NSS_DECLASSIFY(key->publicValue.data, key->publicValue.len); /* Declassifying public key to avoid false positive */
    *privKey = key;
    return SECSuccess;

cleanup:
    PORT_FreeArena(arena, PR_TRUE);
    return rv;
}

/* 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.
 */

SECStatus
EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
                  const unsigned char *seed, int seedlen)
{
    return ec_NewKey(ecParams, privKey, seed, seedlen);
}

/* Generate a random private key using the algorithm A.4.1 or A.4.2 of ANSI X9.62,
 * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
 * random number generator.
 */


SECStatus
ec_GenerateRandomPrivateKey(ECParams *ecParams, SECItem *privKey)
{
    SECStatus rv = SECFailure;

    unsigned int len = EC_GetScalarSize(ecParams);

    if (privKey->len != len || privKey->data == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    const ECMethod *method = ec_get_method_from_name(ecParams->name);
    if (method == NULL || method->scalar_validate == NULL) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    uint8_t leading_coeff_mask;
    switch (ecParams->name) {
        case ECCurve_Ed25519:
        case ECCurve25519:
        case ECCurve_NIST_P256:
        case ECCurve_NIST_P384:
            leading_coeff_mask = 0xff;
            break;
        case ECCurve_NIST_P521:
            leading_coeff_mask = 0x01;
            break;
        default:
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
            return SECFailure;
    }

    /* The rejection sampling method from FIPS 186-5 A.4.2 */
    int count = 100;
    do {
        rv = RNG_GenerateGlobalRandomBytes(privKey->data, len);
        if (rv != SECSuccess) {
            PORT_SetError(SEC_ERROR_NEED_RANDOM);
            return SECFailure;
        }
        privKey->data[0] &= leading_coeff_mask;
        NSS_CLASSIFY(privKey->data, privKey->len);
        rv = method->scalar_validate(privKey);
    } while (rv != SECSuccess && --count > 0);

    if (rv != SECSuccess) { // implies count == 0
        PORT_SetError(SEC_ERROR_BAD_KEY);
    }

    return rv;
}

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

SECStatus
EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
{
    SECStatus rv = SECFailure;
    SECItem privKeyRand = { siBuffer, NULL, 0 };

    if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    SECITEM_AllocItem(NULL, &privKeyRand, EC_GetScalarSize(ecParams));
    if (privKeyRand.data == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        rv = SECFailure;
        goto cleanup;
    }
    rv = ec_GenerateRandomPrivateKey(ecParams, &privKeyRand);
    if (rv != SECSuccess || privKeyRand.data == NULL) {
        goto cleanup;
    }
    /* generate public key */
    CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyRand.data, privKeyRand.len));

cleanup:
    if (privKeyRand.data) {
        SECITEM_ZfreeItem(&privKeyRand, PR_FALSE);
    }
#if EC_DEBUG
    printf("EC_NewKey returning %s\n",
           (rv == SECSuccess) ? "success" : "failure");
#endif

    return rv;
}

/* Validates an EC public key as described in Section 5.2.2 of
 * X9.62. The ECDH primitive when used without the cofactor does
 * not address small subgroup attacks, which may occur when the
 * public key is not valid. These attacks can be prevented by
 * validating the public key before using ECDH.
 */

SECStatus
EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
{
    if (!ecParams || ecParams->name == ECCurve_noName ||
        !publicValue || !publicValue->len) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /* Uses curve specific code for point validation. */
    if (ecParams->fieldID.type != ec_field_plain) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    const ECMethod *method = ec_get_method_from_name(ecParams->name);
    if (method == NULL || method->pt_validate == NULL) {
        /* unknown curve */
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    SECStatus rv = method->pt_validate(publicValue);
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_BAD_KEY);
    }
    return rv;
}

/*
** 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)
{
    if (!publicValue || !publicValue->len ||
        !ecParams || ecParams->name == ECCurve_noName ||
        !privateValue || !privateValue->len || !derivedSecret) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /*
     * Make sure the point is on the requested curve to avoid
     * certain small subgroup attacks.
     */

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

    /* Perform curve specific multiplication using ECMethod */
    if (ecParams->fieldID.type != ec_field_plain) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    const ECMethod *method = ec_get_method_from_name(ecParams->name);
    if (method == NULL || method->pt_validate == NULL ||
        method->pt_mul == NULL) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    memset(derivedSecret, 0, sizeof(*derivedSecret));
    derivedSecret = SECITEM_AllocItem(NULL, derivedSecret, EC_GetScalarSize(ecParams));
    if (derivedSecret == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return SECFailure;
    }

    SECStatus rv = method->pt_mul(derivedSecret, privateValue, publicValue);
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_BAD_KEY);
        SECITEM_ZfreeItem(derivedSecret, PR_FALSE);
    }
    return rv;
}

/* Computes the ECDSA signature (a concatenation of two values r and s)
 * on the digest using the given key and the random value kb (used in
 * computing s).
 */


static SECStatus
ec_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
                      const SECItem *digest, const unsigned char *kb, const int kblen)
{
    ECParams *ecParams = NULL;
    unsigned olen; /* length in bytes of the base point order */

    /* Check args */
    if (!key || !signature || !digest || !kb || (kblen <= 0)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    ecParams = &(key->ecParams);
    olen = ecParams->order.len;
    if (signature->data == NULL) {
        /* a call to get the signature length only */
        signature->len = 2 * olen;
        return SECSuccess;
    }
    if (signature->len < 2 * olen) {
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
        return SECFailure;
    }

    /* Perform curve specific signature using ECMethod */
    if (ecParams->fieldID.type != ec_field_plain) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    const ECMethod *method = ec_get_method_from_name(ecParams->name);
    if (method == NULL || method->sign_digest == NULL) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    SECStatus rv = method->sign_digest(key, signature, digest, kb, kblen);
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    }

#if EC_DEBUG
    printf("ECDSA signing with seed %s\n",
           (rv == SECSuccess) ? "succeeded" : "failed");
#endif
    return rv;
}

SECStatus
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
                         const SECItem *digest, const unsigned char *kb, const int kblen)
{
#if EC_DEBUG || EC_DOUBLECHECK
    SECItem *signature2 = SECITEM_AllocItem(NULL, NULL, signature->len);
    SECStatus signSuccess = ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
    SECStatus signSuccessDouble = ec_SignDigestWithSeed(key, signature2, digest, kb, kblen);
    int signaturesEqual = NSS_SecureMemcmp(signature->data, signature2->data, signature->len);
    SECStatus rv;

    if ((signaturesEqual == 0) && (signSuccess == SECSuccess) && (signSuccessDouble == SECSuccess)) {
        rv = SECSuccess;
    } else {
        rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA signing with seed %s after signing twice\n", (rv == SECSuccess) ? "succeeded" : "failed");
#endif

    SECITEM_FreeItem(signature2, PR_TRUE);
    return rv;
#else
    return ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
#endif
}

/*
** Computes the ECDSA signature on the digest using the given key
** and a random seed.
*/

SECStatus
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest)
{
    SECItem nonceRand = { siBuffer, NULL, 0 };

    if (!key) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /* Generate random value k */
    SECITEM_AllocItem(NULL, &nonceRand, EC_GetScalarSize(&key->ecParams));
    if (nonceRand.data == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return SECFailure;
    }

    SECStatus rv = ec_GenerateRandomPrivateKey(&key->ecParams, &nonceRand);
    if (rv != SECSuccess) {
        goto cleanup;
    }

    /* Generate ECDSA signature with the specified k value */
    rv = ECDSA_SignDigestWithSeed(key, signature, digest, nonceRand.data, nonceRand.len);
    NSS_DECLASSIFY(signature->data, signature->len);

cleanup:
    SECITEM_ZfreeItem(&nonceRand, PR_FALSE);

#if EC_DEBUG
    printf("ECDSA signing %s\n",
           (rv == SECSuccess) ? "succeeded" : "failed");
#endif

    return rv;
}

/*
** Checks the signature on the given digest using the key provided.
**
** The key argument must represent a valid EC public key (a point on
** the relevant curve).  If it is not a valid point, then the behavior
** of this function is undefined.  In cases where a public key might
** not be valid, use EC_ValidatePublicKey to check.
*/

SECStatus
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
                   const SECItem *digest)
{
    SECStatus rv = SECFailure;
    ECParams *ecParams = NULL;

    /* Check args */
    if (!key || !signature || !digest) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    ecParams = &(key->ecParams);

    /* Perform curve specific signature verification using ECMethod */
    if (ecParams->fieldID.type != ec_field_plain) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    const ECMethod *method = ec_get_method_from_name(ecParams->name);
    if (method == NULL || method->verify_digest == NULL) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    rv = method->verify_digest(key, signature, digest);
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    }

#if EC_DEBUG
    printf("ECDSA verification %s\n",
           (rv == SECSuccess) ? "succeeded" : "failed");
#endif

    return rv;
}

/*EdDSA: Currently only Ed22519 is implemented.*/

/*
** Computes the EdDSA signature on the message using the given key.
*/


SECStatus
ec_ED25519_public_key_validate(const ECPublicKey *key)
{
    if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    return ec_ED25519_pt_validate(&key->publicValue);
}

SECStatus
ec_ED25519_private_key_validate(const ECPrivateKey *key)
{
    if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {

        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    return ec_ED25519_scalar_validate(&key->privateValue);
}

SECStatus
ED_SignMessage(ECPrivateKey *key, SECItem *signature, const SECItem *msg)
{
    if (!msg || !signature || signature->len != Ed25519_SIGN_LEN) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (ec_ED25519_private_key_validate(key) != SECSuccess) {
        return SECFailure; /* error code set by ec_ED25519_scalar_validate. */
    }

    if (signature->data) {
        Hacl_Ed25519_sign(signature->data, key->privateValue.data, msg->len,
                          msg->data);
    }
    signature->len = ED25519_SIGN_LEN;
    BLAPI_CLEAR_STACK(2048);
    return SECSuccess;
}

/*
** Checks the signature on the given message using the key provided.
*/


SECStatus
ED_VerifyMessage(ECPublicKey *key, const SECItem *signature,
                 const SECItem *msg)
{
    if (!msg || !signature || !signature->data || signature->len != Ed25519_SIGN_LEN) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (ec_ED25519_public_key_validate(key) != SECSuccess) {
        return SECFailure; /* error code set by ec_ED25519_pt_validate. */
    }

    bool rv = Hacl_Ed25519_verify(key->publicValue.data, msg->len, msg->data,
                                  signature->data);
    BLAPI_CLEAR_STACK(2048);

#if EC_DEBUG
    printf("ED_VerifyMessage returning %s\n",
           (rv) ? "success" : "failure");
#endif

    if (rv) {
        return SECSuccess;
    }

    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    return SECFailure;
}

SECStatus
ED_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey)
{
    /* Currently supporting only Ed25519.*/
    if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != Ed25519_PUBLIC_KEYLEN) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (ec_ED25519_scalar_validate(privateKey) != SECSuccess) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    Hacl_Ed25519_secret_to_public(publicKey->data, privateKey->data);
    return SECSuccess;
}

SECStatus
X25519_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey)
{
    SECStatus rv = SECFailure;
    /* Currently supporting only X25519.*/
    if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != X25519_PUBLIC_KEYLEN) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    const ECMethod *method = ec_get_method_from_name(ECCurve25519);
    if (method == NULL || method->pt_mul == NULL) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    rv = method->pt_mul(publicKey, (SECItem *)privateKey, NULL);
    return rv;
}

SECStatus
EC_DerivePublicKey(const SECItem *privateKey, const ECParams *ecParams, SECItem *publicKey)
{
    if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != EC_GetPointSize(ecParams)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    const ECMethod *method = ec_get_method_from_name(ecParams->name);
    if (method == NULL || method->pt_mul == NULL) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
        return SECFailure;
    }

    return method->pt_mul(publicKey, (SECItem *)privateKey, NULL);
}

Messung V0.5
C=95 H=92 G=93

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge