Beispiel #1
0
/* Create an ECDHE key pair for a given curve */
SECStatus
ssl_CreateECDHEphemeralKeyPair(const namedGroupDef *ecGroup,
                               sslEphemeralKeyPair **keyPair)
{
    SECKEYPrivateKey *privKey = NULL;
    SECKEYPublicKey *pubKey = NULL;
    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
    sslEphemeralKeyPair *pair;

    if (ssl_NamedGroup2ECParams(NULL, ecGroup, &ecParams) != SECSuccess) {
        return SECFailure;
    }
    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);
    SECITEM_FreeItem(&ecParams, PR_FALSE);

    if (!privKey || !pubKey ||
        !(pair = ssl_NewEphemeralKeyPair(ecGroup, privKey, pubKey))) {
        if (privKey) {
            SECKEY_DestroyPrivateKey(privKey);
        }
        if (pubKey) {
            SECKEY_DestroyPublicKey(pubKey);
        }
        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
        return SECFailure;
    }

    *keyPair = pair;
    return SECSuccess;
}
Beispiel #2
0
/* Create an ECDHE key pair for a given curve */
SECStatus
ssl_CreateECDHEphemeralKeyPair(const sslSocket *ss,
                               const sslNamedGroupDef *ecGroup,
                               sslEphemeralKeyPair **keyPair)
{
    SECKEYPrivateKey *privKey = NULL;
    SECKEYPublicKey *pubKey = NULL;
    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
    sslEphemeralKeyPair *pair;

    if (ssl_NamedGroup2ECParams(NULL, ecGroup, &ecParams) != SECSuccess) {
        return SECFailure;
    }
    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, ss->pkcs11PinArg);
    SECITEM_FreeItem(&ecParams, PR_FALSE);

    if (!privKey || !pubKey ||
        !(pair = ssl_NewEphemeralKeyPair(ecGroup, privKey, pubKey))) {
        if (privKey) {
            SECKEY_DestroyPrivateKey(privKey);
        }
        if (pubKey) {
            SECKEY_DestroyPublicKey(pubKey);
        }
        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
        return SECFailure;
    }

    *keyPair = pair;
    SSL_TRC(50, ("%d: SSL[%d]: Create ECDH ephemeral key %d",
                 SSL_GETPID(), ss ? ss->fd : NULL, ecGroup->name));
    PRINT_BUF(50, (ss, "Public Key", pubKey->u.ec.publicValue.data,
                   pubKey->u.ec.publicValue.len));
#ifdef TRACE
    if (ssl_trace >= 50) {
        SECItem d = { siBuffer, NULL, 0 };
        SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey,
                                             CKA_VALUE, &d);
        if (rv == SECSuccess) {
            PRINT_BUF(50, (ss, "Private Key", d.data, d.len));
            SECITEM_FreeItem(&d, PR_FALSE);
        } else {
            SSL_TRC(50, ("Error extracting private key"));
        }
    }
#endif
    return SECSuccess;
}
Beispiel #3
0
/*
** Take an encoded key share and make a public key out of it.
*/
SECStatus
ssl_ImportECDHKeyShare(sslSocket *ss, SECKEYPublicKey *peerKey,
                       SSL3Opaque *b, PRUint32 length,
                       const sslNamedGroupDef *ecGroup)
{
    SECStatus rv;
    SECItem ecPoint = { siBuffer, NULL, 0 };

    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));

    if (!length) {
        PORT_SetError(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE);
        return SECFailure;
    }

    /* Fail if the ec point uses compressed representation */
    if (b[0] != EC_POINT_FORM_UNCOMPRESSED &&
        ecGroup->name != ssl_grp_ec_curve25519) {
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
        return SECFailure;
    }

    peerKey->keyType = ecKey;
    /* Set up the encoded params */
    rv = ssl_NamedGroup2ECParams(peerKey->arena, ecGroup,
                                 &peerKey->u.ec.DEREncodedParams);
    if (rv != SECSuccess) {
        ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE);
        return SECFailure;
    }
    if (ecGroup->name == ssl_grp_ec_curve25519) {
        peerKey->u.ec.encoding = ECPoint_XOnly;
    } else {
        peerKey->u.ec.encoding = ECPoint_Uncompressed;
    }

    /* copy publicValue in peerKey */
    ecPoint.data = b;
    ecPoint.len = length;

    rv = SECITEM_CopyItem(peerKey->arena, &peerKey->u.ec.publicValue, &ecPoint);
    if (rv != SECSuccess) {
        return SECFailure;
    }

    return SECSuccess;
}
Beispiel #4
0
SECStatus
ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
    PLArenaPool *arena = NULL;
    SECKEYPublicKey *peerKey = NULL;
    PRBool isTLS;
    SECStatus rv;
    int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
    SSL3AlertDescription desc = illegal_parameter;
    SSL3Hashes hashes;
    SECItem signature = { siBuffer, NULL, 0 };
    SSLHashType hashAlg = ssl_hash_none;

    SECItem ec_params = { siBuffer, NULL, 0 };
    SECItem ec_point = { siBuffer, NULL, 0 };
    unsigned char paramBuf[3]; /* only for curve_type == named_curve */
    const namedGroupDef *ecGroup;

    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);

    ec_params.len = sizeof paramBuf;
    ec_params.data = paramBuf;
    rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
    if (rv != SECSuccess) {
        goto loser; /* malformed. */
    }

    /* Fail if the curve is not a named curve */
    if (ec_params.data[0] != ec_type_named) {
        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
        desc = handshake_failure;
        goto alert_loser;
    }
    ecGroup = ssl_LookupNamedGroup(ec_params.data[1] << 8 | ec_params.data[2]);
    if (!ecGroup || ecGroup->type != group_type_ec) {
        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
        desc = handshake_failure;
        goto alert_loser;
    }

    rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
    if (rv != SECSuccess) {
        goto loser; /* malformed. */
    }

    /* Fail if the provided point has length 0. */
    if (!ec_point.len) {
        /* desc and errCode are initialized already */
        goto alert_loser;
    }

    /* Fail if the ec point uses compressed representation. */
    if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
        errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
        desc = handshake_failure;
        goto alert_loser;
    }

    if (ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
        SSLSignatureAndHashAlg sigAndHash;
        rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
                                                   &sigAndHash);
        if (rv != SECSuccess) {
            goto loser; /* malformed or unsupported. */
        }
        rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
            ss, &sigAndHash, ss->sec.peerCert);
        if (rv != SECSuccess) {
            goto loser;
        }
        hashAlg = sigAndHash.hashAlg;
    }

    rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
    if (rv != SECSuccess) {
        goto loser; /* malformed. */
    }

    if (length != 0) {
        if (isTLS)
            desc = decode_error;
        goto alert_loser; /* malformed. */
    }

    PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
                   ec_params.len));
    PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));

    /* failures after this point are not malformed handshakes. */
    /* TLS: send decrypt_error if signature failed. */
    desc = isTLS ? decrypt_error : handshake_failure;

    /*
     *  check to make sure the hash is signed by right guy
     */
    rv = ssl3_ComputeECDHKeyHash(hashAlg, ec_params, ec_point,
                                 &ss->ssl3.hs.client_random,
                                 &ss->ssl3.hs.server_random,
                                 &hashes, ss->opt.bypassPKCS11);

    if (rv != SECSuccess) {
        errCode =
            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
        goto alert_loser;
    }
    rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
                                 isTLS, ss->pkcs11PinArg);
    if (rv != SECSuccess) {
        errCode =
            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
        goto alert_loser;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        errCode = SEC_ERROR_NO_MEMORY;
        goto loser;
    }

    peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
    if (peerKey == NULL) {
        errCode = SEC_ERROR_NO_MEMORY;
        goto loser;
    }

    peerKey->arena = arena;
    peerKey->keyType = ecKey;

    /* set up EC parameters in peerKey */
    rv = ssl_NamedGroup2ECParams(arena, ecGroup,
                                 &peerKey->u.ec.DEREncodedParams);
    if (rv != SECSuccess) {
        /* we should never get here since we already
         * checked that we are dealing with a supported curve
         */
        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
        goto alert_loser;
    }

    /* copy publicValue in peerKey */
    if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point)) {
        errCode = SEC_ERROR_NO_MEMORY;
        goto loser;
    }
    peerKey->pkcs11Slot = NULL;
    peerKey->pkcs11ID = CK_INVALID_HANDLE;

    ss->sec.peerKey = peerKey;
    return SECSuccess;

alert_loser:
    (void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
    if (arena) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    PORT_SetError(errCode);
    return SECFailure;
}