/src/nss/lib/ssl/tls13signature.c
Line | Count | Source |
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 | 2.72k | { |
21 | 2.72k | SECAlgorithmID *newAlgID = PORT_ArenaZNew(arena, SECAlgorithmID); |
22 | 2.72k | SECOidTag algTag = SEC_OID_UNKNOWN; |
23 | 2.72k | SECOidTag hashAlgTag = SEC_OID_UNKNOWN; |
24 | 2.72k | SECStatus rv; |
25 | | |
26 | 2.72k | 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 | 924 | case ssl_sig_rsa_pss_rsae_sha256: |
32 | 924 | case ssl_sig_rsa_pss_pss_sha256: |
33 | 924 | algTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE; |
34 | 924 | hashAlgTag = SEC_OID_SHA256; |
35 | 924 | break; |
36 | 411 | case ssl_sig_rsa_pss_rsae_sha384: |
37 | 411 | case ssl_sig_rsa_pss_pss_sha384: |
38 | 411 | algTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE; |
39 | 411 | hashAlgTag = SEC_OID_SHA384; |
40 | 411 | break; |
41 | 551 | case ssl_sig_rsa_pss_rsae_sha512: |
42 | 551 | case ssl_sig_rsa_pss_pss_sha512: |
43 | 551 | algTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE; |
44 | 551 | hashAlgTag = SEC_OID_SHA512; |
45 | 551 | break; |
46 | | /* the curve comes from the key and should have already been |
47 | | * enforced at a different level */ |
48 | 841 | case ssl_sig_ecdsa_secp256r1_sha256: |
49 | 841 | algTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; |
50 | 841 | hashAlgTag = SEC_OID_SHA256; |
51 | 841 | break; |
52 | 0 | case ssl_sig_ecdsa_secp384r1_sha384: |
53 | 0 | algTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; |
54 | 0 | hashAlgTag = SEC_OID_SHA384; |
55 | 0 | break; |
56 | 0 | case ssl_sig_ecdsa_secp521r1_sha512: |
57 | 0 | algTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; |
58 | 0 | hashAlgTag = SEC_OID_SHA512; |
59 | 0 | 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 | 0 | case ssl_sig_ed25519: |
72 | 0 | case ssl_sig_ed448: |
73 | | |
74 | | /* sha1 hashes in sigs are explicitly disallowed in TLS 1.3 or greater */ |
75 | 0 | case ssl_sig_ecdsa_sha1: |
76 | | |
77 | | /* rsa pkcs1 sigs are explicitly disallowed in TLS 1.3 and greater */ |
78 | 0 | case ssl_sig_rsa_pkcs1_sha1: |
79 | 0 | case ssl_sig_rsa_pkcs1_sha256: |
80 | 0 | case ssl_sig_rsa_pkcs1_sha384: |
81 | 0 | case ssl_sig_rsa_pkcs1_sha512: |
82 | | |
83 | | /* dsa sigs are explicitly disallowed in TLS 1.3 and greater */ |
84 | 0 | case ssl_sig_dsa_sha1: |
85 | 0 | case ssl_sig_dsa_sha256: |
86 | 0 | case ssl_sig_dsa_sha384: |
87 | 0 | case ssl_sig_dsa_sha512: |
88 | | |
89 | | /* special sig variants that aren't supported in TLS 1.3 or greater */ |
90 | 0 | case ssl_sig_rsa_pkcs1_sha1md5: |
91 | 0 | case ssl_sig_none: |
92 | 0 | break; |
93 | 2.72k | } |
94 | | |
95 | | /* the earlier code should have made sure none of the unsupported |
96 | | * algorithms were accepted */ |
97 | 2.72k | PORT_Assert(algTag != SEC_OID_UNKNOWN); |
98 | 2.72k | if (algTag == SEC_OID_UNKNOWN) { |
99 | 0 | PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
100 | 0 | return NULL; |
101 | 0 | } |
102 | | |
103 | | /* now get the algorithm ID algTag will override whatever is normally |
104 | | * selected from the key */ |
105 | 2.72k | rv = SEC_CreateSignatureAlgorithmID(arena, newAlgID, algTag, hashAlgTag, |
106 | 2.72k | NULL, privKey, pubKey); |
107 | 2.72k | if (rv != SECSuccess) { |
108 | 0 | return NULL; |
109 | 0 | } |
110 | 2.72k | return newAlgID; |
111 | 2.72k | } |
112 | | |
113 | | tlsSignOrVerifyContext |
114 | | tls_CreateSignOrVerifyContext(SECKEYPrivateKey *privKey, |
115 | | SECKEYPublicKey *pubKey, |
116 | | SSLSignatureScheme scheme, sslSignOrVerify type, |
117 | | SECItem *signature, void *pwArg) |
118 | 2.72k | { |
119 | 2.72k | PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
120 | 2.72k | tlsSignOrVerifyContext newCtx = { type, { NULL } }; |
121 | 2.72k | SECStatus rv; |
122 | | |
123 | 2.72k | if (!arena) { |
124 | 0 | goto loser; |
125 | 0 | } |
126 | | |
127 | 2.72k | if (type == sig_sign) { |
128 | 2.72k | PORT_Assert(privKey); |
129 | 2.72k | } else { |
130 | 0 | PORT_Assert(pubKey); |
131 | 0 | } |
132 | | |
133 | | /* we use sigAlgID here because it automatically formats parameters |
134 | | * for PSS. */ |
135 | 2.72k | SECAlgorithmID *sigAlgID = tls_GetSignatureAlgorithmId(arena, scheme, |
136 | 2.72k | privKey, pubKey); |
137 | 2.72k | if (sigAlgID == NULL) { |
138 | 0 | goto loser; |
139 | 0 | } |
140 | 2.72k | if (type == sig_sign) { |
141 | 2.72k | newCtx.u.sig = SGN_NewContextWithAlgorithmID(sigAlgID, privKey); |
142 | 2.72k | if (!newCtx.u.sig) { |
143 | 0 | goto loser; |
144 | 0 | } |
145 | 2.72k | rv = SGN_Begin(newCtx.u.sig); |
146 | 2.72k | } else { |
147 | 0 | newCtx.u.vfy = VFY_CreateContextWithAlgorithmID(pubKey, signature, |
148 | 0 | sigAlgID, NULL, pwArg); |
149 | 0 | if (!newCtx.u.vfy) { |
150 | 0 | goto loser; |
151 | 0 | } |
152 | 0 | rv = VFY_Begin(newCtx.u.vfy); |
153 | 0 | } |
154 | 2.72k | if (rv != SECSuccess) { |
155 | 0 | goto loser; |
156 | 0 | } |
157 | 2.72k | PORT_FreeArena(arena, PR_FALSE); |
158 | 2.72k | return newCtx; |
159 | | |
160 | 0 | loser: |
161 | 0 | tls_DestroySignOrVerifyContext(newCtx); |
162 | 0 | if (arena) { |
163 | 0 | PORT_FreeArena(arena, PR_FALSE); |
164 | 0 | } |
165 | 0 | return newCtx; /* pointer already set to NULL by destroy */ |
166 | 2.72k | } |
167 | | |
168 | | SECStatus |
169 | | tls_SignOrVerifyUpdate(tlsSignOrVerifyContext ctx, const unsigned char *buf, |
170 | | int len) |
171 | 8.18k | { |
172 | 8.18k | SECStatus rv; |
173 | 8.18k | if (ctx.type == sig_sign) { |
174 | 8.18k | rv = SGN_Update(ctx.u.sig, buf, len); |
175 | 8.18k | } else { |
176 | 0 | rv = VFY_Update(ctx.u.vfy, buf, len); |
177 | 0 | } |
178 | 8.18k | return rv; |
179 | 8.18k | } |
180 | | |
181 | | SECStatus |
182 | | tls_SignOrVerifyEnd(tlsSignOrVerifyContext ctx, SECItem *sig) |
183 | 2.72k | { |
184 | 2.72k | SECStatus rv; |
185 | 2.72k | if (ctx.type == sig_sign) { |
186 | 2.72k | rv = SGN_End(ctx.u.sig, sig); |
187 | 2.72k | } else { |
188 | | /* sig was already set in the context VFY_CreateContext */ |
189 | 0 | rv = VFY_End(ctx.u.vfy); |
190 | 0 | } |
191 | | /* destroy the context on success */ |
192 | 2.72k | if (rv == SECSuccess) { |
193 | 2.72k | tls_DestroySignOrVerifyContext(ctx); |
194 | 2.72k | } |
195 | 2.72k | return rv; |
196 | 2.72k | } |
197 | | |
198 | | void |
199 | | tls_DestroySignOrVerifyContext(tlsSignOrVerifyContext ctx) |
200 | 2.72k | { |
201 | 2.72k | if (ctx.type == sig_sign) { |
202 | 2.72k | if (ctx.u.sig) { |
203 | 2.72k | SGN_DestroyContext(ctx.u.sig, PR_TRUE); |
204 | 2.72k | } |
205 | 2.72k | } else { |
206 | 0 | if (ctx.u.vfy) { |
207 | 0 | VFY_DestroyContext(ctx.u.vfy, PR_TRUE); |
208 | 0 | } |
209 | 0 | } |
210 | 2.72k | } |