2 * Copyright (c) 2002 - 2007, Stockholms universitet
3 * (Stockholm University, Stockholm Sweden)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the university nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include "rxgk_locl.h"
41 krb5_context _rxgkk5ctx
;
44 rxgk_crypto_start(void)
46 if (_rxgkk5ctx
== NULL
)
47 krb5_init_context(&_rxgkk5ctx
);
51 rxgk_crypto_init(struct rxgk_keyblock
*tk
, key_stuff
*k
)
56 ret
= krb5_keyblock_init(_rxgkk5ctx
, tk
->enctype
, tk
->data
, tk
->length
,
62 ret
= krb5_crypto_init (_rxgkk5ctx
, &tk_kb
, tk
->enctype
, &k
->ks_scrypto
);
63 krb5_free_keyblock_contents(_rxgkk5ctx
, &tk_kb
);
67 k
->ks_overhead
= krb5_crypto_overhead(_rxgkk5ctx
, k
->ks_scrypto
);
71 ret
= krb5_crypto_get_checksum_type(_rxgkk5ctx
, k
->ks_scrypto
, &type
);
72 ret
= krb5_checksumsize(_rxgkk5ctx
, type
, &k
->ks_cksumsize
);
80 uint32_t channel_and_seq
;
85 getheader(struct rx_connection
*conn
,
86 struct rx_packet
*pkt
,
87 struct rxgk_pkg_hdr
*h
)
91 /* Collect selected pkt fields */
92 h
->call_number
= htonl(pkt
->header
.callNumber
);
93 t
= ((pkt
->header
.cid
& RX_CHANNELMASK
) << (32 - RX_CIDSHIFT
))
94 | ((pkt
->header
.seq
& 0x3fffffff));
95 h
->channel_and_seq
= htonl(t
);
99 rxgk_prepare_packet(struct rx_packet
*p
, struct rx_connection
*conn
,
100 int level
, key_stuff
*k
, end_stuff
*e
,
101 int keyusage_enc
, int keyusage_mic
)
103 size_t len
= rx_GetDataSize(p
);
104 size_t off
= rx_GetSecurityHeaderSize(conn
);
107 if (level
== RXGK_WIRE_ENCRYPT
) {
108 krb5_data plain
, cipher
;
109 struct rxgk_pkg_hdr hdr
;
111 memset(&cipher
, 0, sizeof(cipher
));
113 assert(sizeof(hdr
) == off
);
115 plain
.length
= len
+ sizeof(hdr
);
116 plain
.data
= osi_Alloc(plain
.length
);
118 getheader(conn
, p
, &hdr
);
119 hdr
.svcid_len
= htonl((conn
->serviceId
<< 16) | rx_GetDataSize(p
));
120 memcpy(plain
.data
, &hdr
, sizeof(hdr
));
122 rx_packetread(p
, off
, len
, (unsigned char*)plain
.data
+ sizeof(hdr
));
124 ret
= krb5_encrypt(_rxgkk5ctx
, k
->ks_scrypto
, keyusage_enc
,
125 plain
.data
, plain
.length
, &cipher
);
126 osi_Free(plain
.data
, plain
.length
);
129 if (cipher
.length
> len
+ sizeof(hdr
))
130 rxi_RoundUpPacket(p
, cipher
.length
- len
- sizeof(hdr
));
131 rx_packetwrite(p
, 0, cipher
.length
, cipher
.data
);
132 rx_SetDataSize(p
, cipher
.length
);
133 krb5_data_free(&cipher
);
135 } else if (level
== RXGK_WIRE_INTEGRITY
) {
139 memset(&cksum
, 0, sizeof(cksum
));
141 scratch
.length
= len
;
142 scratch
.data
= osi_Alloc(scratch
.length
);
144 rx_packetread(p
, off
, len
, scratch
.data
);
146 ret
= krb5_create_checksum(_rxgkk5ctx
, k
->ks_scrypto
, keyusage_mic
, 0,
147 scratch
.data
, scratch
.length
, &cksum
);
148 osi_Free(scratch
.data
, scratch
.length
);
149 rx_SetDataSize(p
, len
);
151 /* write header into trailier */
153 } else if (level
== RXGK_WIRE_AUTH_ONLY
) {
165 rxgk_check_packet(struct rx_packet
*p
, struct rx_connection
*conn
,
166 int level
, key_stuff
*k
, end_stuff
*e
,
167 int keyusage_enc
, int keyusage_mic
)
169 size_t len
= rx_GetDataSize(p
);
170 size_t off
= rx_GetSecurityHeaderSize(conn
);
173 if (level
== RXGK_WIRE_ENCRYPT
) {
174 krb5_data cipher
, plain
;
175 struct rxgk_pkg_hdr hdr
;
181 cipher
.data
= osi_Alloc(cipher
.length
);
183 getheader(conn
, p
, &hdr
);
184 rx_packetread(p
, 0, cipher
.length
, cipher
.data
);
186 ret
= krb5_decrypt(_rxgkk5ctx
, k
->ks_scrypto
, keyusage_enc
,
187 cipher
.data
, cipher
.length
, &plain
);
188 osi_Free(cipher
.data
, cipher
.length
);
190 if (plain
.length
< sizeof(hdr
)) {
194 if (memcmp(plain
.data
, &hdr
, 8) != 0) {
198 len
= ntohl(((uint32_t *)plain
.data
)[2]) & 0xffff;
199 if (len
> plain
.length
- sizeof(hdr
)) {
203 rx_packetwrite(p
, off
,
205 (unsigned char*)plain
.data
+ sizeof(hdr
));
206 rx_SetDataSize(p
, len
);
208 krb5_data_free(&plain
);
211 } else if (level
== RXGK_WIRE_INTEGRITY
) {
215 memset(&cksum
, 0, sizeof(cksum
));
217 scratch
.length
= len
;
218 scratch
.data
= osi_Alloc(scratch
.length
);
221 rx_packetread(p
, off
, len
-off
, scratch
.data
);
222 scratch
.length
= len
- off
;
224 ret
= krb5_verify_checksum(_rxgkk5ctx
, k
->ks_scrypto
, keyusage_mic
,
225 scratch
.data
, scratch
.length
,
227 osi_Free(scratch
.data
, scratch
.length
);
229 rx_SetDataSize(p
, len
- off
);
231 } else if (level
== RXGK_WIRE_AUTH_ONLY
) {
241 rxgk_encrypt_buffer(RXGK_Token
*in
, RXGK_Token
*out
,
242 struct rxgk_keyblock
*key
, int keyusage
)
244 krb5_keyblock keyblock
;
249 ret
= krb5_keyblock_init(_rxgkk5ctx
, key
->enctype
,
250 key
->data
, key
->length
, &keyblock
);
254 ret
= krb5_crypto_init(_rxgkk5ctx
, &keyblock
, 0, &crypto
);
255 krb5_free_keyblock_contents(_rxgkk5ctx
, &keyblock
);
259 ret
= krb5_encrypt(_rxgkk5ctx
, crypto
, keyusage
, in
->val
, in
->len
, &data
);
260 krb5_crypto_destroy(_rxgkk5ctx
, crypto
);
262 out
->val
= data
.data
;
263 out
->len
= data
.length
;
269 rxgk_decrypt_buffer(RXGK_Token
*in
, RXGK_Token
*out
,
270 struct rxgk_keyblock
*key
, int keyusage
)
272 krb5_keyblock keyblock
;
277 ret
= krb5_keyblock_init(_rxgkk5ctx
, key
->enctype
,
278 key
->data
, key
->length
, &keyblock
);
282 ret
= krb5_crypto_init(_rxgkk5ctx
, &keyblock
, 0, &crypto
);
283 krb5_free_keyblock_contents(_rxgkk5ctx
, &keyblock
);
287 ret
= krb5_decrypt(_rxgkk5ctx
, crypto
, keyusage
, in
->val
, in
->len
, &data
);
288 krb5_crypto_destroy(_rxgkk5ctx
, crypto
);
290 out
->val
= data
.data
;
291 out
->len
= data
.length
;
298 print_key(char *name
, struct rxgk_keyblock
*key
)
302 fprintf(stderr
, "type: %s", name
);
303 for (i
= 0; i
< key
->length
; i
++)
304 fprintf(stderr
, " %02x", ((unsigned char*)key
->data
)[i
]);
305 fprintf(stderr
, "\n");
310 rxgk_derive_transport_key(struct rxgk_keyblock
*k0
,
311 struct rxgk_keyblock
*tk
,
312 uint32_t epoch
, uint32_t cid
, int64_t start_time
)
316 /* XXX get real key */
318 if (k0
->enctype
!= RXGK_CRYPTO_AES256_CTS_HMAC_SHA1_96
) {
323 tk
->enctype
= RXGK_CRYPTO_AES256_CTS_HMAC_SHA1_96
;
325 tk
->data
= malloc(tk
->length
);
326 if (tk
->data
== NULL
)
329 x
= epoch
* 4711 + cid
* 33 + start_time
;
330 for (i
= 0; i
< tk
->length
; i
++) {
331 x
+= i
* 3 + ((unsigned char *)k0
->data
)[i
%k0
->length
];
332 ((unsigned char *)tk
->data
)[i
] = 0x23 + x
* 47;
336 print_key("k0: ", k0
);
337 print_key("tk: ", tk
);
343 #endif /* AFS_HCRYPTO */