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 }