2 chronyd/chronyc - Programs for keeping computer clocks accurate.
4 **********************************************************************
5 * Copyright (C) Miroslav Lichvar 2020
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 **********************************************************************
22 =======================================================================
24 NTS Authenticator and Encrypted Extension Fields extension field
31 #include "nts_ntp_auth.h"
40 uint16_t nonce_length
;
41 uint16_t ciphertext_length
;
44 /* ================================================== */
47 get_padding_length(int length
)
49 return length
% 4U ? 4 - length
% 4U : 0;
52 /* ================================================== */
55 get_padded_length(int length
)
57 return length
+ get_padding_length(length
);
60 /* ================================================== */
63 NNA_GenerateAuthEF(NTP_Packet
*packet
, NTP_PacketInfo
*info
, SIV_Instance siv
,
64 const unsigned char *nonce
, int nonce_length
,
65 const unsigned char *plaintext
, int plaintext_length
,
68 int auth_length
, ciphertext_length
, assoc_length
;
69 int nonce_padding
, ciphertext_padding
, additional_padding
;
70 unsigned char *ciphertext
, *body
;
71 struct AuthHeader
*header
;
73 assert(sizeof (*header
) == 4);
75 if (nonce_length
<= 0 || plaintext_length
< 0) {
76 DEBUG_LOG("Invalid nonce/plaintext length");
80 assoc_length
= info
->length
;
81 ciphertext_length
= SIV_GetTagLength(siv
) + plaintext_length
;
82 nonce_padding
= get_padding_length(nonce_length
);
83 ciphertext_padding
= get_padding_length(ciphertext_length
);
84 min_ef_length
= get_padded_length(min_ef_length
);
86 auth_length
= sizeof (*header
) + nonce_length
+ nonce_padding
+
87 ciphertext_length
+ ciphertext_padding
;
88 additional_padding
= MAX(min_ef_length
- auth_length
- 4, 0);
89 additional_padding
= MAX(NTS_MIN_UNPADDED_NONCE_LENGTH
- nonce_length
- nonce_padding
,
91 auth_length
+= additional_padding
;
93 if (!NEF_AddBlankField(packet
, info
, NTP_EF_NTS_AUTH_AND_EEF
, auth_length
,
95 DEBUG_LOG("Could not add EF");
99 header
->nonce_length
= htons(nonce_length
);
100 header
->ciphertext_length
= htons(ciphertext_length
);
102 body
= (unsigned char *)(header
+ 1);
103 ciphertext
= body
+ nonce_length
+ nonce_padding
;
105 memcpy(body
, nonce
, nonce_length
);
106 memset(body
+ nonce_length
, 0, nonce_padding
);
108 if (!SIV_Encrypt(siv
, nonce
, nonce_length
, packet
, assoc_length
,
109 plaintext
, plaintext_length
, ciphertext
, ciphertext_length
)) {
110 DEBUG_LOG("SIV encrypt failed");
114 memset(ciphertext
+ ciphertext_length
, 0, ciphertext_padding
+ additional_padding
);
119 /* ================================================== */
122 NNA_DecryptAuthEF(NTP_Packet
*packet
, NTP_PacketInfo
*info
, SIV_Instance siv
, int ef_start
,
123 unsigned char *plaintext
, int buffer_length
, int *plaintext_length
)
125 unsigned int siv_tag_length
, nonce_length
, ciphertext_length
;
126 unsigned char *nonce
, *ciphertext
;
127 int ef_type
, ef_body_length
;
129 struct AuthHeader
*header
;
131 if (!NEF_ParseField(packet
, info
->length
, ef_start
,
132 NULL
, &ef_type
, &ef_body
, &ef_body_length
))
135 if (ef_type
!= NTP_EF_NTS_AUTH_AND_EEF
)
140 nonce_length
= ntohs(header
->nonce_length
);
141 ciphertext_length
= ntohs(header
->ciphertext_length
);
143 if (get_padded_length(nonce_length
) +
144 get_padded_length(ciphertext_length
) > ef_body_length
)
147 nonce
= (unsigned char *)(header
+ 1);
148 ciphertext
= (unsigned char *)(header
+ 1) + get_padded_length(nonce_length
);
150 siv_tag_length
= SIV_GetTagLength(siv
);
152 if (nonce_length
< 1 ||
153 ciphertext_length
< siv_tag_length
||
154 ciphertext_length
- siv_tag_length
> buffer_length
) {
155 DEBUG_LOG("Unexpected nonce/ciphertext length");
159 if (ef_body_length
< sizeof (*header
) +
160 NTS_MIN_UNPADDED_NONCE_LENGTH
+ get_padded_length(ciphertext_length
)) {
161 DEBUG_LOG("Missing padding");
165 *plaintext_length
= ciphertext_length
- siv_tag_length
;
167 if (!SIV_Decrypt(siv
, nonce
, nonce_length
, packet
, info
->length
- ef_body_length
- 4,
168 ciphertext
, ciphertext_length
, plaintext
, *plaintext_length
)) {
169 DEBUG_LOG("SIV decrypt failed");