tls13psk.c (6096B)
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 { 22 23 sslSocket *ss = ssl_FindSocket(fd); 24 if (!ss) { 25 SSL_DBG(("%d: SSL[%d]: bad socket in SSLExp_SetExternalPsk", 26 SSL_GETPID(), fd)); 27 return SECFailure; 28 } 29 30 if (!key || !identity || !identityLen || identityLen > 0xFFFF || 31 (hash != ssl_hash_sha256 && hash != ssl_hash_sha384)) { 32 PORT_SetError(SEC_ERROR_INVALID_ARGS); 33 return SECFailure; 34 } 35 36 SECItem label = { siBuffer, CONST_CAST(unsigned char, identity), identityLen }; 37 sslPsk *psk = tls13_MakePsk(PK11_ReferenceSymKey(key), ssl_psk_external, 38 hash, &label); 39 if (!psk) { 40 PORT_SetError(SEC_ERROR_NO_MEMORY); 41 return SECFailure; 42 } 43 psk->zeroRttSuite = zeroRttSuite; 44 psk->maxEarlyData = maxEarlyData; 45 SECStatus rv = SECFailure; 46 47 ssl_Get1stHandshakeLock(ss); 48 ssl_GetSSL3HandshakeLock(ss); 49 50 if (ss->psk) { 51 PORT_SetError(SEC_ERROR_INVALID_ARGS); 52 tls13_DestroyPsk(psk); 53 } else { 54 ss->psk = psk; 55 rv = SECSuccess; 56 tls13_ResetHandshakePsks(ss, &ss->ssl3.hs.psks); 57 } 58 59 ssl_ReleaseSSL3HandshakeLock(ss); 60 ssl_Release1stHandshakeLock(ss); 61 62 return rv; 63 } 64 65 SECStatus 66 SSLExp_AddExternalPsk(PRFileDesc *fd, PK11SymKey *key, const PRUint8 *identity, 67 unsigned int identityLen, SSLHashType hash) 68 { 69 return SSLExp_AddExternalPsk0Rtt(fd, key, identity, identityLen, 70 hash, TLS_NULL_WITH_NULL_NULL, 0); 71 } 72 73 SECStatus 74 SSLExp_RemoveExternalPsk(PRFileDesc *fd, const PRUint8 *identity, unsigned int identityLen) 75 { 76 if (!identity || !identityLen) { 77 PORT_SetError(SEC_ERROR_INVALID_ARGS); 78 return SECFailure; 79 } 80 81 sslSocket *ss = ssl_FindSocket(fd); 82 if (!ss) { 83 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPSK", 84 SSL_GETPID(), fd)); 85 return SECFailure; 86 } 87 88 SECItem removeIdentity = { siBuffer, 89 (unsigned char *)identity, 90 identityLen }; 91 92 SECStatus rv; 93 ssl_Get1stHandshakeLock(ss); 94 ssl_GetSSL3HandshakeLock(ss); 95 96 if (!ss->psk || SECITEM_CompareItem(&ss->psk->label, &removeIdentity) != SECEqual) { 97 PORT_SetError(SEC_ERROR_NO_KEY); 98 rv = SECFailure; 99 } else { 100 tls13_DestroyPsk(ss->psk); 101 ss->psk = NULL; 102 tls13_ResetHandshakePsks(ss, &ss->ssl3.hs.psks); 103 rv = SECSuccess; 104 } 105 106 ssl_ReleaseSSL3HandshakeLock(ss); 107 ssl_Release1stHandshakeLock(ss); 108 109 return rv; 110 } 111 112 sslPsk * 113 tls13_CopyPsk(sslPsk *opsk) 114 { 115 if (!opsk || !opsk->key) { 116 return NULL; 117 } 118 119 sslPsk *psk = PORT_ZNew(sslPsk); 120 if (!psk) { 121 return NULL; 122 } 123 124 SECStatus rv = SECITEM_CopyItem(NULL, &psk->label, &opsk->label); 125 if (rv != SECSuccess) { 126 PORT_Free(psk); 127 return NULL; 128 } 129 /* We should only have the initial key. Binder keys 130 * are derived during the handshake. */ 131 PORT_Assert(opsk->type == ssl_psk_external); 132 PORT_Assert(opsk->key); 133 PORT_Assert(!opsk->binderKey); 134 psk->hash = opsk->hash; 135 psk->type = opsk->type; 136 psk->key = opsk->key ? PK11_ReferenceSymKey(opsk->key) : NULL; 137 psk->binderKey = opsk->binderKey ? PK11_ReferenceSymKey(opsk->binderKey) : NULL; 138 return psk; 139 } 140 141 void 142 tls13_DestroyPsk(sslPsk *psk) 143 { 144 if (!psk) { 145 return; 146 } 147 if (psk->key) { 148 PK11_FreeSymKey(psk->key); 149 psk->key = NULL; 150 } 151 if (psk->binderKey) { 152 PK11_FreeSymKey(psk->binderKey); 153 psk->binderKey = NULL; 154 } 155 SECITEM_ZfreeItem(&psk->label, PR_FALSE); 156 PORT_ZFree(psk, sizeof(*psk)); 157 } 158 159 void 160 tls13_DestroyPskList(PRCList *list) 161 { 162 PRCList *cur_p; 163 while (!PR_CLIST_IS_EMPTY(list)) { 164 cur_p = PR_LIST_TAIL(list); 165 PR_REMOVE_LINK(cur_p); 166 tls13_DestroyPsk((sslPsk *)cur_p); 167 } 168 } 169 170 sslPsk * 171 tls13_MakePsk(PK11SymKey *key, SSLPskType pskType, SSLHashType hashType, const SECItem *label) 172 { 173 sslPsk *psk = PORT_ZNew(sslPsk); 174 if (!psk) { 175 PORT_SetError(SEC_ERROR_NO_MEMORY); 176 return NULL; 177 } 178 psk->type = pskType; 179 psk->hash = hashType; 180 psk->key = key; 181 182 /* Label is NULL in the resumption case. */ 183 if (label) { 184 PORT_Assert(psk->type != ssl_psk_resume); 185 SECStatus rv = SECITEM_CopyItem(NULL, &psk->label, label); 186 if (rv != SECSuccess) { 187 PORT_SetError(SEC_ERROR_NO_MEMORY); 188 tls13_DestroyPsk(psk); 189 return NULL; 190 } 191 } 192 193 return psk; 194 } 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 { 201 tls13_DestroyPskList(list); 202 PORT_Assert(!ss->xtnData.selectedPsk); 203 ss->xtnData.selectedPsk = NULL; 204 if (ss->psk) { 205 PORT_Assert(ss->psk->type == ssl_psk_external); 206 PORT_Assert(ss->psk->key); 207 PORT_Assert(!ss->psk->binderKey); 208 209 sslPsk *epsk = tls13_MakePsk(PK11_ReferenceSymKey(ss->psk->key), 210 ss->psk->type, ss->psk->hash, &ss->psk->label); 211 if (!epsk) { 212 return SECFailure; 213 } 214 epsk->zeroRttSuite = ss->psk->zeroRttSuite; 215 epsk->maxEarlyData = ss->psk->maxEarlyData; 216 PR_APPEND_LINK(&epsk->link, list); 217 } 218 return SECSuccess; 219 }