Exemplo n.º 1
0
/*
** Called from ssl3_HandleClientKeyExchange()
*/
SECStatus
ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
				     PRUint32 length,
                                     SECKEYPublicKey *srvrPubKey,
                                     SECKEYPrivateKey *srvrPrivKey)
{
    PK11SymKey *      pms;
    SECStatus         rv;
    SECKEYPublicKey   clntPubKey;
    CK_MECHANISM_TYPE	target;
    PRBool isTLS, isTLS12;

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

    clntPubKey.keyType = ecKey;
    clntPubKey.u.ec.DEREncodedParams.len = 
	srvrPubKey->u.ec.DEREncodedParams.len;
    clntPubKey.u.ec.DEREncodedParams.data = 
	srvrPubKey->u.ec.DEREncodedParams.data;

    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue, 
	                               1, &b, &length);
    if (rv != SECSuccess) {
	SEND_ALERT
	return SECFailure;	/* XXX Who sets the error code?? */
    }
Exemplo n.º 2
0
SECStatus
ssl3_ExtConsumeHandshakeVariable(const sslSocket *ss, SECItem *i,
                                 PRUint32 bytes, PRUint8 **b,
                                 PRUint32 *length)
{
    return ssl3_ConsumeHandshakeVariable((sslSocket *)ss, i, bytes, b, length);
}
Exemplo n.º 3
0
/* Go through hello extensions in |b| and deserialize
 * them into the list in |ss->ssl3.hs.remoteExtensions|.
 * The only checking we do in this point is for duplicates.
 *
 * IMPORTANT: This list just contains pointers to the incoming
 * buffer so they can only be used during ClientHello processing.
 */
SECStatus
ssl3_ParseExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length)
{
    /* Clean out the extensions list. */
    ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions);

    while (*length) {
        SECStatus rv;
        PRUint32 extension_type;
        SECItem extension_data = { siBuffer, NULL, 0 };
        TLSExtension *extension;
        PRCList *cursor;

        /* Get the extension's type field */
        rv = ssl3_ConsumeHandshakeNumber(ss, &extension_type, 2, b, length);
        if (rv != SECSuccess) {
            return SECFailure; /* alert already sent */
        }

        /* Check whether an extension has been sent multiple times. */
        for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions);
             cursor != &ss->ssl3.hs.remoteExtensions;
             cursor = PR_NEXT_LINK(cursor)) {
            if (((TLSExtension *)cursor)->type == extension_type) {
                (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
                return SECFailure;
            }
        }

        /* Get the data for this extension, so we can pass it or skip it. */
        rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
        if (rv != SECSuccess) {
            return rv; /* alert already sent */
        }

        SSL_TRC(10, ("%d: SSL3[%d]: parsed extension %d len=%u",
                     SSL_GETPID(), ss->fd, extension_type, extension_data.len));

        extension = PORT_ZNew(TLSExtension);
        if (!extension) {
            return SECFailure;
        }

        extension->type = (PRUint16)extension_type;
        extension->data = extension_data;
        PR_APPEND_LINK(&extension->link, &ss->ssl3.hs.remoteExtensions);
    }

    return SECSuccess;
}
Exemplo n.º 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;
}
Exemplo n.º 5
0
/*
** Called from ssl3_HandleClientKeyExchange()
*/
SECStatus
ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
                                 PRUint32 length,
                                 sslKeyPair *serverKeyPair)
{
    PK11SymKey *pms;
    SECStatus rv;
    SECKEYPublicKey clntPubKey;
    CK_MECHANISM_TYPE target;
    PRBool isTLS, isTLS12;
    int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH;

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

    clntPubKey.keyType = ecKey;
    clntPubKey.u.ec.DEREncodedParams.len =
        serverKeyPair->pubKey->u.ec.DEREncodedParams.len;
    clntPubKey.u.ec.DEREncodedParams.data =
        serverKeyPair->pubKey->u.ec.DEREncodedParams.data;

    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
                                       1, &b, &length);
    if (rv != SECSuccess) {
        PORT_SetError(errCode);
        return SECFailure;
    }

    /* we have to catch the case when the client's public key has length 0. */
    if (!clntPubKey.u.ec.publicValue.len) {
        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
        PORT_SetError(errCode);
        return SECFailure;
    }

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

    if (isTLS12) {
        target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
    } else if (isTLS) {
        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
    } else {
        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
    }

    /*  Determine the PMS */
    pms = PK11_PubDeriveWithKDF(serverKeyPair->privKey, &clntPubKey,
                                PR_FALSE, NULL, NULL,
                                CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
                                CKD_NULL, NULL, NULL);

    if (pms == NULL) {
        /* last gasp.  */
        errCode = ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
        PORT_SetError(errCode);
        return SECFailure;
    }

    rv = ssl3_InitPendingCipherSpec(ss, pms);
    PK11_FreeSymKey(pms);
    if (rv != SECSuccess) {
        /* error code set by ssl3_InitPendingCipherSpec */
        return SECFailure;
    }
    return SECSuccess;
}
Exemplo n.º 6
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;
    SSLSignatureScheme sigScheme;

    SECItem ec_params = { siBuffer, NULL, 0 };
    SECItem ec_point = { siBuffer, NULL, 0 };
    unsigned char paramBuf[3];
    const sslNamedGroupDef *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->keaType != ssl_kea_ecdh) {
        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 is not uncompressed for any curve that's not 25519. */
    if (ecGroup->name != ssl_grp_ec_curve25519 &&
        ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
        errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
        desc = handshake_failure;
        goto alert_loser;
    }

    PORT_Assert(ss->ssl3.prSpec->version <= SSL_LIBRARY_VERSION_TLS_1_2);
    if (ss->ssl3.prSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
        rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
        if (rv != SECSuccess) {
            goto loser; /* malformed or unsupported. */
        }
        rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme,
                                                 ss->sec.peerCert);
        if (rv != SECSuccess) {
            goto loser;
        }
        hashAlg = ssl_SignatureSchemeToHashType(sigScheme);
    } else {
        /* Use ssl_hash_none to represent the MD5+SHA1 combo. */
        hashAlg = ssl_hash_none;
        sigScheme = ssl_sig_none;
    }

    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);

    if (rv != SECSuccess) {
        errCode =
            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
        goto alert_loser;
    }
    rv = ssl3_VerifySignedHashes(ss, sigScheme, &hashes, &signature);
    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;

    /* create public key from point data */
    rv = ssl_ImportECDHKeyShare(ss, peerKey, ec_point.data, ec_point.len,
                                ecGroup);
    if (rv != SECSuccess) {
        /* error code is set */
        desc = handshake_failure;
        errCode = PORT_GetError();
        goto alert_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;
}