/src/nss/lib/ssl/tls13psk.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "nss.h" |
8 | | #include "pk11func.h" |
9 | | #include "ssl.h" |
10 | | #include "sslproto.h" |
11 | | #include "sslimpl.h" |
12 | | #include "ssl3exthandle.h" |
13 | | #include "tls13exthandle.h" |
14 | | #include "tls13hkdf.h" |
15 | | #include "tls13psk.h" |
16 | | |
17 | | SECStatus |
18 | | SSLExp_AddExternalPsk0Rtt(PRFileDesc *fd, PK11SymKey *key, const PRUint8 *identity, |
19 | | unsigned int identityLen, SSLHashType hash, |
20 | | PRUint16 zeroRttSuite, PRUint32 maxEarlyData) |
21 | 0 | { |
22 | |
|
23 | 0 | sslSocket *ss = ssl_FindSocket(fd); |
24 | 0 | if (!ss) { |
25 | 0 | SSL_DBG(("%d: SSL[%d]: bad socket in SSLExp_SetExternalPsk", |
26 | 0 | SSL_GETPID(), fd)); |
27 | 0 | return SECFailure; |
28 | 0 | } |
29 | | |
30 | 0 | if (!key || !identity || !identityLen || identityLen > 0xFFFF || |
31 | 0 | (hash != ssl_hash_sha256 && hash != ssl_hash_sha384)) { |
32 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
33 | 0 | return SECFailure; |
34 | 0 | } |
35 | | |
36 | 0 | SECItem label = { siBuffer, CONST_CAST(unsigned char, identity), identityLen }; |
37 | 0 | sslPsk *psk = tls13_MakePsk(PK11_ReferenceSymKey(key), ssl_psk_external, |
38 | 0 | hash, &label); |
39 | 0 | if (!psk) { |
40 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
41 | 0 | return SECFailure; |
42 | 0 | } |
43 | 0 | psk->zeroRttSuite = zeroRttSuite; |
44 | 0 | psk->maxEarlyData = maxEarlyData; |
45 | 0 | SECStatus rv = SECFailure; |
46 | |
|
47 | 0 | ssl_Get1stHandshakeLock(ss); |
48 | 0 | ssl_GetSSL3HandshakeLock(ss); |
49 | |
|
50 | 0 | if (ss->psk) { |
51 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
52 | 0 | tls13_DestroyPsk(psk); |
53 | 0 | } else { |
54 | 0 | ss->psk = psk; |
55 | 0 | rv = SECSuccess; |
56 | 0 | tls13_ResetHandshakePsks(ss, &ss->ssl3.hs.psks); |
57 | 0 | } |
58 | |
|
59 | 0 | ssl_ReleaseSSL3HandshakeLock(ss); |
60 | 0 | ssl_Release1stHandshakeLock(ss); |
61 | |
|
62 | 0 | return rv; |
63 | 0 | } |
64 | | |
65 | | SECStatus |
66 | | SSLExp_AddExternalPsk(PRFileDesc *fd, PK11SymKey *key, const PRUint8 *identity, |
67 | | unsigned int identityLen, SSLHashType hash) |
68 | 0 | { |
69 | 0 | return SSLExp_AddExternalPsk0Rtt(fd, key, identity, identityLen, |
70 | 0 | hash, TLS_NULL_WITH_NULL_NULL, 0); |
71 | 0 | } |
72 | | |
73 | | SECStatus |
74 | | SSLExp_RemoveExternalPsk(PRFileDesc *fd, const PRUint8 *identity, unsigned int identityLen) |
75 | 0 | { |
76 | 0 | if (!identity || !identityLen) { |
77 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
78 | 0 | return SECFailure; |
79 | 0 | } |
80 | | |
81 | 0 | sslSocket *ss = ssl_FindSocket(fd); |
82 | 0 | if (!ss) { |
83 | 0 | SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPSK", |
84 | 0 | SSL_GETPID(), fd)); |
85 | 0 | return SECFailure; |
86 | 0 | } |
87 | | |
88 | 0 | SECItem removeIdentity = { siBuffer, |
89 | 0 | (unsigned char *)identity, |
90 | 0 | identityLen }; |
91 | |
|
92 | 0 | SECStatus rv; |
93 | 0 | ssl_Get1stHandshakeLock(ss); |
94 | 0 | ssl_GetSSL3HandshakeLock(ss); |
95 | |
|
96 | 0 | if (!ss->psk || SECITEM_CompareItem(&ss->psk->label, &removeIdentity) != SECEqual) { |
97 | 0 | PORT_SetError(SEC_ERROR_NO_KEY); |
98 | 0 | rv = SECFailure; |
99 | 0 | } else { |
100 | 0 | tls13_DestroyPsk(ss->psk); |
101 | 0 | ss->psk = NULL; |
102 | 0 | tls13_ResetHandshakePsks(ss, &ss->ssl3.hs.psks); |
103 | 0 | rv = SECSuccess; |
104 | 0 | } |
105 | |
|
106 | 0 | ssl_ReleaseSSL3HandshakeLock(ss); |
107 | 0 | ssl_Release1stHandshakeLock(ss); |
108 | |
|
109 | 0 | return rv; |
110 | 0 | } |
111 | | |
112 | | sslPsk * |
113 | | tls13_CopyPsk(sslPsk *opsk) |
114 | 0 | { |
115 | 0 | if (!opsk || !opsk->key) { |
116 | 0 | return NULL; |
117 | 0 | } |
118 | | |
119 | 0 | sslPsk *psk = PORT_ZNew(sslPsk); |
120 | 0 | if (!psk) { |
121 | 0 | return NULL; |
122 | 0 | } |
123 | | |
124 | 0 | SECStatus rv = SECITEM_CopyItem(NULL, &psk->label, &opsk->label); |
125 | 0 | if (rv != SECSuccess) { |
126 | 0 | PORT_Free(psk); |
127 | 0 | return NULL; |
128 | 0 | } |
129 | | /* We should only have the initial key. Binder keys |
130 | | * are derived during the handshake. */ |
131 | 0 | PORT_Assert(opsk->type == ssl_psk_external); |
132 | 0 | PORT_Assert(opsk->key); |
133 | 0 | PORT_Assert(!opsk->binderKey); |
134 | 0 | psk->hash = opsk->hash; |
135 | 0 | psk->type = opsk->type; |
136 | 0 | psk->key = opsk->key ? PK11_ReferenceSymKey(opsk->key) : NULL; |
137 | 0 | psk->binderKey = opsk->binderKey ? PK11_ReferenceSymKey(opsk->binderKey) : NULL; |
138 | 0 | return psk; |
139 | 0 | } |
140 | | |
141 | | void |
142 | | tls13_DestroyPsk(sslPsk *psk) |
143 | 7.93k | { |
144 | 7.93k | if (!psk) { |
145 | 7.93k | return; |
146 | 7.93k | } |
147 | 0 | if (psk->key) { |
148 | 0 | PK11_FreeSymKey(psk->key); |
149 | 0 | psk->key = NULL; |
150 | 0 | } |
151 | 0 | if (psk->binderKey) { |
152 | 0 | PK11_FreeSymKey(psk->binderKey); |
153 | 0 | psk->binderKey = NULL; |
154 | 0 | } |
155 | 0 | SECITEM_ZfreeItem(&psk->label, PR_FALSE); |
156 | 0 | PORT_ZFree(psk, sizeof(*psk)); |
157 | 0 | } |
158 | | |
159 | | void |
160 | | tls13_DestroyPskList(PRCList *list) |
161 | 24.2k | { |
162 | 24.2k | PRCList *cur_p; |
163 | 24.2k | while (!PR_CLIST_IS_EMPTY(list)) { |
164 | 0 | cur_p = PR_LIST_TAIL(list); |
165 | 0 | PR_REMOVE_LINK(cur_p); |
166 | 0 | tls13_DestroyPsk((sslPsk *)cur_p); |
167 | 0 | } |
168 | 24.2k | } |
169 | | |
170 | | sslPsk * |
171 | | tls13_MakePsk(PK11SymKey *key, SSLPskType pskType, SSLHashType hashType, const SECItem *label) |
172 | 0 | { |
173 | 0 | sslPsk *psk = PORT_ZNew(sslPsk); |
174 | 0 | if (!psk) { |
175 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
176 | 0 | return NULL; |
177 | 0 | } |
178 | 0 | psk->type = pskType; |
179 | 0 | psk->hash = hashType; |
180 | 0 | psk->key = key; |
181 | | |
182 | | /* Label is NULL in the resumption case. */ |
183 | 0 | if (label) { |
184 | 0 | PORT_Assert(psk->type != ssl_psk_resume); |
185 | 0 | SECStatus rv = SECITEM_CopyItem(NULL, &psk->label, label); |
186 | 0 | if (rv != SECSuccess) { |
187 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
188 | 0 | tls13_DestroyPsk(psk); |
189 | 0 | return NULL; |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | 0 | return psk; |
194 | 0 | } |
195 | | |
196 | | /* Destroy any existing PSKs in |list| then copy |
197 | | * in the configured |ss->psk|, if any.*/ |
198 | | SECStatus |
199 | | tls13_ResetHandshakePsks(sslSocket *ss, PRCList *list) |
200 | 7.93k | { |
201 | 7.93k | tls13_DestroyPskList(list); |
202 | 7.93k | PORT_Assert(!ss->xtnData.selectedPsk); |
203 | 7.93k | ss->xtnData.selectedPsk = NULL; |
204 | 7.93k | if (ss->psk) { |
205 | 0 | PORT_Assert(ss->psk->type == ssl_psk_external); |
206 | 0 | PORT_Assert(ss->psk->key); |
207 | 0 | PORT_Assert(!ss->psk->binderKey); |
208 | |
|
209 | 0 | sslPsk *epsk = tls13_MakePsk(PK11_ReferenceSymKey(ss->psk->key), |
210 | 0 | ss->psk->type, ss->psk->hash, &ss->psk->label); |
211 | 0 | if (!epsk) { |
212 | 0 | return SECFailure; |
213 | 0 | } |
214 | 0 | epsk->zeroRttSuite = ss->psk->zeroRttSuite; |
215 | 0 | epsk->maxEarlyData = ss->psk->maxEarlyData; |
216 | 0 | PR_APPEND_LINK(&epsk->link, list); |
217 | 0 | } |
218 | 7.93k | return SECSuccess; |
219 | 7.93k | } |