2 * Copyright (c) 2017 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/socket.h>
32 #include <sys/queue.h>
33 #include <sys/syslog.h>
34 #include <sys/errno.h>
36 #include <sys/mcache.h>
37 #include <mach/vm_param.h>
38 #include <kern/locks.h>
41 #include <net/route.h>
42 #include <net/net_osdep.h>
43 #include <netinet6/ipsec.h>
44 #include <netinet6/esp.h>
45 #include <netinet6/esp_chachapoly.h>
46 #include <netkey/key.h>
47 #include <netkey/keydb.h>
48 #include <corecrypto/cc.h>
49 #include <libkern/crypto/chacha20poly1305.h>
51 #define ESP_CHACHAPOLY_SALT_LEN 4
52 #define ESP_CHACHAPOLY_KEY_LEN 32
53 #define ESP_CHACHAPOLY_NONCE_LEN 12
55 // The minimum alignment is documented in KALLOC_LOG2_MINALIGN
56 // which isn't accessible from here. Current minimum is 8.
57 _Static_assert(_Alignof(chacha20poly1305_ctx
) <= 8,
58 "Alignment guarantee is broken");
60 #if ((( 8 * (ESP_CHACHAPOLY_KEY_LEN + ESP_CHACHAPOLY_SALT_LEN)) != ESP_CHACHAPOLY_KEYBITS_WITH_SALT) || \
61 (ESP_CHACHAPOLY_KEY_LEN != CCCHACHA20_KEY_NBYTES) || \
62 (ESP_CHACHAPOLY_NONCE_LEN != CCCHACHA20POLY1305_NONCE_NBYTES))
63 #error "Invalid sizes"
66 extern lck_mtx_t
*sadb_mutex
;
68 typedef struct _esp_chachapoly_ctx
{
69 chacha20poly1305_ctx ccp_ctx
;
70 uint8_t ccp_salt
[ESP_CHACHAPOLY_SALT_LEN
];
72 } esp_chachapoly_ctx_s
, *esp_chachapoly_ctx_t
;
75 #define ESP_ASSERT(_cond, _format, ...) \
78 panic("%s:%d " _format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
82 #define ESP_CHECK_ARG(_arg) ESP_ASSERT(_arg != NULL, #_arg "is NULL")
84 #define _esp_log(_level, _format, ...) \
85 log(_level, "%s:%d " _format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
86 #define esp_log_err(_format, ...) _esp_log(LOG_ERR, _format, ##__VA_ARGS__)
88 #define _esp_packet_log(_level, _format, ...) \
89 ipseclog((_level, "%s:%d " _format, __FUNCTION__, __LINE__, ##__VA_ARGS__))
90 #define esp_packet_log_err(_format, ...) _esp_packet_log(LOG_ERR, _format, ##__VA_ARGS__)
93 esp_chachapoly_mature(struct secasvar
*sav
)
95 const struct esp_algorithm
*algo
;
99 if ((sav
->flags
& SADB_X_EXT_OLD
) != 0) {
100 esp_log_err("ChaChaPoly is incompatible with SADB_X_EXT_OLD");
103 if ((sav
->flags
& SADB_X_EXT_DERIV
) != 0) {
104 esp_log_err("ChaChaPoly is incompatible with SADB_X_EXT_DERIV");
108 if (sav
->alg_enc
!= SADB_X_EALG_CHACHA20POLY1305
) {
109 esp_log_err("ChaChaPoly unsupported algorithm %d",
114 if (sav
->key_enc
== NULL
) {
115 esp_log_err("ChaChaPoly key is missing");
119 algo
= esp_algorithm_lookup(sav
->alg_enc
);
121 esp_log_err("ChaChaPoly lookup failed for algorithm %d",
126 if (sav
->key_enc
->sadb_key_bits
!= ESP_CHACHAPOLY_KEYBITS_WITH_SALT
) {
127 esp_log_err("ChaChaPoly invalid key length %d bits",
128 sav
->key_enc
->sadb_key_bits
);
136 esp_chachapoly_schedlen(__unused
const struct esp_algorithm
*algo
)
138 return sizeof(esp_chachapoly_ctx_s
);
142 esp_chachapoly_schedule(__unused
const struct esp_algorithm
*algo
,
143 struct secasvar
*sav
)
145 esp_chachapoly_ctx_t esp_ccp_ctx
;
149 if (sav
->ivlen
!= ESP_CHACHAPOLY_IV_LEN
) {
150 esp_log_err("Invalid ivlen %u", sav
->ivlen
);
153 if (_KEYLEN(sav
->key_enc
) != ESP_CHACHAPOLY_KEY_LEN
+ ESP_CHACHAPOLY_SALT_LEN
) {
154 esp_log_err("Invalid key len %u", _KEYLEN(sav
->key_enc
));
157 LCK_MTX_ASSERT(sadb_mutex
, LCK_MTX_ASSERT_OWNED
);
159 esp_ccp_ctx
= (esp_chachapoly_ctx_t
)sav
->sched
;
161 rc
= chacha20poly1305_init(&esp_ccp_ctx
->ccp_ctx
,
162 (const uint8_t *)_KEYBUF(sav
->key_enc
));
164 esp_log_err("chacha20poly1305_init returned %d", rc
);
168 memcpy(esp_ccp_ctx
->ccp_salt
,
169 (const uint8_t *)_KEYBUF(sav
->key_enc
) + ESP_CHACHAPOLY_KEY_LEN
,
170 sizeof(esp_ccp_ctx
->ccp_salt
));
172 esp_ccp_ctx
->ccp_implicit_iv
= ((sav
->flags
& SADB_X_EXT_IIV
) != 0);
178 esp_chachapoly_encrypt_finalize(struct secasvar
*sav
,
180 unsigned int tag_bytes
)
182 esp_chachapoly_ctx_t esp_ccp_ctx
;
187 if (tag_bytes
!= ESP_CHACHAPOLY_ICV_LEN
) {
188 esp_log_err("Invalid tag_bytes %u", tag_bytes
);
192 esp_ccp_ctx
= (esp_chachapoly_ctx_t
)sav
->sched
;
193 rc
= chacha20poly1305_finalize(&esp_ccp_ctx
->ccp_ctx
, tag
);
195 esp_log_err("chacha20poly1305_finalize returned %d", rc
);
202 esp_chachapoly_decrypt_finalize(struct secasvar
*sav
,
204 unsigned int tag_bytes
)
206 esp_chachapoly_ctx_t esp_ccp_ctx
;
211 if (tag_bytes
!= ESP_CHACHAPOLY_ICV_LEN
) {
212 esp_log_err("Invalid tag_bytes %u", tag_bytes
);
216 esp_ccp_ctx
= (esp_chachapoly_ctx_t
)sav
->sched
;
217 rc
= chacha20poly1305_verify(&esp_ccp_ctx
->ccp_ctx
, tag
);
219 esp_log_err("chacha20poly1305_finalize returned %d", rc
);
226 esp_chachapoly_encrypt(struct mbuf
*m
, // head of mbuf chain
227 size_t off
, // offset to ESP header
228 __unused
size_t plen
,
229 struct secasvar
*sav
,
230 __unused
const struct esp_algorithm
*algo
,
233 struct mbuf
*s
= m
; // this mbuf
234 int32_t soff
= 0; // offset from the head of mbuf chain (m) to head of this mbuf (s)
235 int32_t sn
= 0; // offset from the head of this mbuf (s) to the body
236 uint8_t *sp
; // buffer of a given encryption round
237 size_t len
; // length of a given encryption round
238 const int32_t ivoff
= (int32_t)off
+ (int32_t)sizeof(struct newesp
); // IV offset
239 int32_t bodyoff
; // body offset
240 int rc
= 0; // return code of corecrypto operations
241 struct newesp esp_hdr
; // ESP header for AAD
242 _Static_assert(sizeof(esp_hdr
) == 8, "Bad size");
243 uint8_t nonce
[ESP_CHACHAPOLY_NONCE_LEN
];
244 esp_chachapoly_ctx_t esp_ccp_ctx
;
248 if (ivlen
!= ESP_CHACHAPOLY_IV_LEN
) {
250 esp_log_err("Invalid ivlen %u", ivlen
);
253 if (sav
->ivlen
!= ESP_CHACHAPOLY_IV_LEN
) {
255 esp_log_err("Invalid sav->ivlen %u", sav
->ivlen
);
259 esp_ccp_ctx
= (esp_chachapoly_ctx_t
)sav
->sched
;
260 if (esp_ccp_ctx
->ccp_implicit_iv
) {
263 bodyoff
= ivoff
+ ivlen
;
265 // check if total packet length is enough to contain ESP + IV
266 if (m
->m_pkthdr
.len
< bodyoff
) {
267 esp_log_err("Packet too short %d < %zu", m
->m_pkthdr
.len
, bodyoff
);
272 rc
= chacha20poly1305_reset(&esp_ccp_ctx
->ccp_ctx
);
275 esp_log_err("chacha20poly1305_reset failed %d", rc
);
279 // RFC 7634 dictates that the 12 byte nonce must be
280 // the 4 byte salt followed by the 8 byte IV.
281 // The IV MUST be non-repeating but does not need to be unpredictable,
282 // so we use 4 bytes of 0 followed by the 4 byte ESP sequence number.
283 // this allows us to use implicit IV -- draft-mglt-ipsecme-implicit-iv
284 memset(sav
->iv
, 0, 4);
285 memcpy(sav
->iv
+ 4, &sav
->seq
, sizeof(sav
->seq
));
286 _Static_assert(4 + sizeof(sav
->seq
) == ESP_CHACHAPOLY_IV_LEN
,
288 memcpy(nonce
, esp_ccp_ctx
->ccp_salt
, ESP_CHACHAPOLY_SALT_LEN
);
289 memcpy(nonce
+ ESP_CHACHAPOLY_SALT_LEN
, sav
->iv
, ESP_CHACHAPOLY_IV_LEN
);
290 _Static_assert(ESP_CHACHAPOLY_SALT_LEN
+ ESP_CHACHAPOLY_IV_LEN
== sizeof(nonce
),
293 rc
= chacha20poly1305_setnonce(&esp_ccp_ctx
->ccp_ctx
, nonce
);
296 esp_log_err("chacha20poly1305_setnonce failed %d", rc
);
300 if (!esp_ccp_ctx
->ccp_implicit_iv
) {
301 m_copyback(m
, ivoff
, ivlen
, sav
->iv
);
303 cc_clear(sizeof(nonce
), nonce
);
305 // Set Additional Authentication Data (AAD)
306 m_copydata(m
, (int)off
, sizeof(esp_hdr
), (void *)&esp_hdr
);
308 rc
= chacha20poly1305_aad(&esp_ccp_ctx
->ccp_ctx
,
313 esp_log_err("chacha20poly1305_aad failed %d", rc
);
318 while (s
!= NULL
&& soff
< bodyoff
) {
319 if (soff
+ s
->m_len
> bodyoff
) {
328 while (s
!= NULL
&& soff
< m
->m_pkthdr
.len
) {
329 len
= (size_t)(s
->m_len
- sn
);
334 sp
= mtod(s
, uint8_t *) + sn
;
336 rc
= chacha20poly1305_encrypt(&esp_ccp_ctx
->ccp_ctx
,
340 esp_log_err("chacha20poly1305_encrypt failed %d", rc
);
348 if (s
== NULL
&& soff
!= m
->m_pkthdr
.len
) {
350 esp_log_err("not enough mbufs %d %d", soff
, m
->m_pkthdr
.len
);
357 esp_chachapoly_decrypt(struct mbuf
*m
, // head of mbuf chain
358 size_t off
, // offset to ESP header
359 struct secasvar
*sav
,
360 __unused
const struct esp_algorithm
*algo
,
363 struct mbuf
*s
= m
; // this mbuf
364 int32_t soff
= 0; // offset from the head of mbuf chain (m) to head of this mbuf (s)
365 int32_t sn
= 0; // offset from the head of this mbuf (s) to the body
366 uint8_t *sp
; // buffer of a given encryption round
367 size_t len
; // length of a given encryption round
368 const int32_t ivoff
= (int32_t)off
+ (int32_t)sizeof(struct newesp
); // IV offset
369 int32_t bodyoff
; // body offset
370 int rc
= 0; // return code of corecrypto operations
371 struct newesp esp_hdr
; // ESP header for AAD
372 _Static_assert(sizeof(esp_hdr
) == 8, "Bad size");
373 uint8_t nonce
[ESP_CHACHAPOLY_NONCE_LEN
];
374 esp_chachapoly_ctx_t esp_ccp_ctx
;
378 if (ivlen
!= ESP_CHACHAPOLY_IV_LEN
) {
380 esp_log_err("Invalid ivlen %u", ivlen
);
383 if (sav
->ivlen
!= ESP_CHACHAPOLY_IV_LEN
) {
385 esp_log_err("Invalid sav->ivlen %u", sav
->ivlen
);
389 esp_ccp_ctx
= (esp_chachapoly_ctx_t
)sav
->sched
;
390 if (esp_ccp_ctx
->ccp_implicit_iv
) {
393 bodyoff
= ivoff
+ ivlen
;
395 // check if total packet length is enough to contain ESP + IV
396 if (m
->m_pkthdr
.len
< bodyoff
) {
397 esp_packet_log_err("Packet too short %d < %zu", m
->m_pkthdr
.len
, bodyoff
);
402 rc
= chacha20poly1305_reset(&esp_ccp_ctx
->ccp_ctx
);
405 esp_log_err("chacha20poly1305_reset failed %d", rc
);
409 m_copydata(m
, (int)off
, sizeof(esp_hdr
), (void *)&esp_hdr
);
411 // RFC 7634 dictates that the 12 byte nonce must be
412 // the 4 byte salt followed by the 8 byte IV.
413 memcpy(nonce
, esp_ccp_ctx
->ccp_salt
, ESP_CHACHAPOLY_SALT_LEN
);
414 if (esp_ccp_ctx
->ccp_implicit_iv
) {
415 // IV is implicit (4 zero bytes followed by the ESP sequence number)
416 memset(nonce
+ ESP_CHACHAPOLY_SALT_LEN
, 0, 4);
417 memcpy(nonce
+ ESP_CHACHAPOLY_SALT_LEN
+ 4, &esp_hdr
.esp_seq
, sizeof(esp_hdr
.esp_seq
));
418 _Static_assert(4 + sizeof(esp_hdr
.esp_seq
) == ESP_CHACHAPOLY_IV_LEN
, "Bad IV length");
420 // copy IV from packet
421 m_copydata(m
, ivoff
, ESP_CHACHAPOLY_IV_LEN
, nonce
+ ESP_CHACHAPOLY_SALT_LEN
);
423 _Static_assert(ESP_CHACHAPOLY_SALT_LEN
+ ESP_CHACHAPOLY_IV_LEN
== sizeof(nonce
),
426 rc
= chacha20poly1305_setnonce(&esp_ccp_ctx
->ccp_ctx
, nonce
);
429 esp_log_err("chacha20poly1305_setnonce failed %d", rc
);
432 cc_clear(sizeof(nonce
), nonce
);
434 // Set Additional Authentication Data (AAD)
435 rc
= chacha20poly1305_aad(&esp_ccp_ctx
->ccp_ctx
,
440 esp_log_err("chacha20poly1305_aad failed %d", rc
);
445 while (s
!= NULL
&& soff
< bodyoff
) {
446 if (soff
+ s
->m_len
> bodyoff
) {
455 while (s
!= NULL
&& soff
< m
->m_pkthdr
.len
) {
456 len
= (size_t)(s
->m_len
- sn
);
461 sp
= mtod(s
, uint8_t *) + sn
;
463 rc
= chacha20poly1305_decrypt(&esp_ccp_ctx
->ccp_ctx
,
467 esp_packet_log_err("chacha20poly1305_decrypt failed %d", rc
);
475 if (s
== NULL
&& soff
!= m
->m_pkthdr
.len
) {
477 esp_packet_log_err("not enough mbufs %d %d", soff
, m
->m_pkthdr
.len
);