tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tls13signature.c (7148B)


      1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
      2 /*
      3 * TLS 1.3 Protocol
      4 *
      5 * This Source Code Form is subject to the terms of the Mozilla Public
      6 * License, v. 2.0. If a copy of the MPL was not distributed with this
      7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      8 #include "sslimpl.h"
      9 #include "cryptohi.h"
     10 #include "keyhi.h"
     11 
     12 /* we put this here because it only affects TLS 1.3, and not TLS 1.2 and earlier
     13 * which use the old sign hashes interface. The TLS 1.3 protocol is friendly to
     14 * algorthims that don't have a signed hashes interface */
     15 /* we generate an algorithm ID rather than just use an OID to support RSAPSS.
     16 * It's generated completely from the scheme */
     17 static SECAlgorithmID *
     18 tls_GetSignatureAlgorithmId(PLArenaPool *arena, SSLSignatureScheme scheme,
     19                            SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey)
     20 {
     21    SECAlgorithmID *newAlgID = PORT_ArenaZNew(arena, SECAlgorithmID);
     22    SECOidTag algTag = SEC_OID_UNKNOWN;
     23    SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
     24    SECStatus rv;
     25 
     26    switch (scheme) {
     27        /* For the algTag the difference between rsa_pss_rsae and
     28         * rsa_pss_pss is in the selection of the cert.
     29         * At this stage, the signatures are the same, so for our
     30         * purposed they are equivalent */
     31        case ssl_sig_rsa_pss_rsae_sha256:
     32        case ssl_sig_rsa_pss_pss_sha256:
     33            algTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
     34            hashAlgTag = SEC_OID_SHA256;
     35            break;
     36        case ssl_sig_rsa_pss_rsae_sha384:
     37        case ssl_sig_rsa_pss_pss_sha384:
     38            algTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
     39            hashAlgTag = SEC_OID_SHA384;
     40            break;
     41        case ssl_sig_rsa_pss_rsae_sha512:
     42        case ssl_sig_rsa_pss_pss_sha512:
     43            algTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
     44            hashAlgTag = SEC_OID_SHA512;
     45            break;
     46        /* the curve comes from the key and should have already been
     47         * enforced at a different level */
     48        case ssl_sig_ecdsa_secp256r1_sha256:
     49            algTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
     50            hashAlgTag = SEC_OID_SHA256;
     51            break;
     52        case ssl_sig_ecdsa_secp384r1_sha384:
     53            algTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
     54            hashAlgTag = SEC_OID_SHA384;
     55            break;
     56        case ssl_sig_ecdsa_secp521r1_sha512:
     57            algTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
     58            hashAlgTag = SEC_OID_SHA512;
     59            break;
     60 
     61        /* the following is unsupported in tls 1.3 and greater, just break.
     62         * We include them here explicitly so we get the compiler warning about
     63         * missing enums in the switch statement. default would be a break anyway.
     64         * That way we'll know to update this table when new algorithms are
     65         * added */
     66 
     67        /* as of now edward curve signatures are not supported in NSS. That
     68         * could change, and this is part the code that would pick up the
     69         * change (need OIDS for the hash variants of these signature, and
     70         * then add them here) */
     71        case ssl_sig_ed25519:
     72        case ssl_sig_ed448:
     73 
     74        /* sha1 hashes in sigs are explicitly disallowed in TLS 1.3 or greater */
     75        case ssl_sig_ecdsa_sha1:
     76 
     77        /* rsa pkcs1 sigs are explicitly disallowed in TLS 1.3 and greater */
     78        case ssl_sig_rsa_pkcs1_sha1:
     79        case ssl_sig_rsa_pkcs1_sha256:
     80        case ssl_sig_rsa_pkcs1_sha384:
     81        case ssl_sig_rsa_pkcs1_sha512:
     82 
     83        /* dsa sigs are explicitly disallowed in TLS 1.3 and greater */
     84        case ssl_sig_dsa_sha1:
     85        case ssl_sig_dsa_sha256:
     86        case ssl_sig_dsa_sha384:
     87        case ssl_sig_dsa_sha512:
     88 
     89        /* special sig variants that aren't supported in TLS 1.3 or greater */
     90        case ssl_sig_rsa_pkcs1_sha1md5:
     91        case ssl_sig_none:
     92            break;
     93    }
     94 
     95    /* the earlier code should have made sure none of the unsupported
     96     * algorithms were accepted */
     97    PORT_Assert(algTag != SEC_OID_UNKNOWN);
     98    if (algTag == SEC_OID_UNKNOWN) {
     99        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    100        return NULL;
    101    }
    102 
    103    /* now get the algorithm ID algTag will override whatever is normally
    104     * selected from the key */
    105    rv = SEC_CreateSignatureAlgorithmID(arena, newAlgID, algTag, hashAlgTag,
    106                                        NULL, privKey, pubKey);
    107    if (rv != SECSuccess) {
    108        return NULL;
    109    }
    110    return newAlgID;
    111 }
    112 
    113 tlsSignOrVerifyContext
    114 tls_CreateSignOrVerifyContext(SECKEYPrivateKey *privKey,
    115                              SECKEYPublicKey *pubKey,
    116                              SSLSignatureScheme scheme, sslSignOrVerify type,
    117                              SECItem *signature, void *pwArg)
    118 {
    119    PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    120    tlsSignOrVerifyContext newCtx = { type, { NULL } };
    121    SECStatus rv;
    122 
    123    if (!arena) {
    124        goto loser;
    125    }
    126 
    127    if (type == sig_sign) {
    128        PORT_Assert(privKey);
    129    } else {
    130        PORT_Assert(pubKey);
    131    }
    132 
    133    /* we use sigAlgID here because it automatically formats parameters
    134     * for PSS. */
    135    SECAlgorithmID *sigAlgID = tls_GetSignatureAlgorithmId(arena, scheme,
    136                                                           privKey, pubKey);
    137    if (sigAlgID == NULL) {
    138        goto loser;
    139    }
    140    if (type == sig_sign) {
    141        newCtx.u.sig = SGN_NewContextWithAlgorithmID(sigAlgID, privKey);
    142        if (!newCtx.u.sig) {
    143            goto loser;
    144        }
    145        rv = SGN_Begin(newCtx.u.sig);
    146    } else {
    147        newCtx.u.vfy = VFY_CreateContextWithAlgorithmID(pubKey, signature,
    148                                                        sigAlgID, NULL, pwArg);
    149        if (!newCtx.u.vfy) {
    150            goto loser;
    151        }
    152        rv = VFY_Begin(newCtx.u.vfy);
    153    }
    154    if (rv != SECSuccess) {
    155        goto loser;
    156    }
    157    PORT_FreeArena(arena, PR_FALSE);
    158    return newCtx;
    159 
    160 loser:
    161    tls_DestroySignOrVerifyContext(newCtx);
    162    if (arena) {
    163        PORT_FreeArena(arena, PR_FALSE);
    164    }
    165    return newCtx; /* pointer already set to NULL by destroy */
    166 }
    167 
    168 SECStatus
    169 tls_SignOrVerifyUpdate(tlsSignOrVerifyContext ctx, const unsigned char *buf,
    170                       int len)
    171 {
    172    SECStatus rv;
    173    if (ctx.type == sig_sign) {
    174        rv = SGN_Update(ctx.u.sig, buf, len);
    175    } else {
    176        rv = VFY_Update(ctx.u.vfy, buf, len);
    177    }
    178    return rv;
    179 }
    180 
    181 SECStatus
    182 tls_SignOrVerifyEnd(tlsSignOrVerifyContext ctx, SECItem *sig)
    183 {
    184    SECStatus rv;
    185    if (ctx.type == sig_sign) {
    186        rv = SGN_End(ctx.u.sig, sig);
    187    } else {
    188        /* sig was already set in the context VFY_CreateContext */
    189        rv = VFY_End(ctx.u.vfy);
    190    }
    191    /* destroy the context on success */
    192    if (rv == SECSuccess) {
    193        tls_DestroySignOrVerifyContext(ctx);
    194    }
    195    return rv;
    196 }
    197 
    198 void
    199 tls_DestroySignOrVerifyContext(tlsSignOrVerifyContext ctx)
    200 {
    201    if (ctx.type == sig_sign) {
    202        if (ctx.u.sig) {
    203            SGN_DestroyContext(ctx.u.sig, PR_TRUE);
    204        }
    205    } else {
    206        if (ctx.u.vfy) {
    207            VFY_DestroyContext(ctx.u.vfy, PR_TRUE);
    208        }
    209    }
    210 }