xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/gssapi/krb5/get_mic.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1*afab4e30Schristos /*	$NetBSD: get_mic.c,v 1.6 2023/06/19 21:41:43 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
36ca1c9b0cSelric #include "gsskrb5_locl.h"
37ca1c9b0cSelric 
38ca1c9b0cSelric #ifdef HEIM_WEAK_CRYPTO
39ca1c9b0cSelric 
40ca1c9b0cSelric static OM_uint32
mic_des(OM_uint32 * minor_status,const gsskrb5_ctx ctx,krb5_context context,gss_qop_t qop_req,const gss_buffer_t message_buffer,gss_buffer_t message_token,krb5_keyblock * key)41ca1c9b0cSelric mic_des
42ca1c9b0cSelric            (OM_uint32 * minor_status,
43ca1c9b0cSelric             const gsskrb5_ctx ctx,
44ca1c9b0cSelric 	    krb5_context context,
45ca1c9b0cSelric             gss_qop_t qop_req,
46ca1c9b0cSelric             const gss_buffer_t message_buffer,
47ca1c9b0cSelric             gss_buffer_t message_token,
48ca1c9b0cSelric 	    krb5_keyblock *key
49ca1c9b0cSelric            )
50ca1c9b0cSelric {
51ca1c9b0cSelric   u_char *p;
52ca1c9b0cSelric   EVP_MD_CTX *md5;
53ca1c9b0cSelric   u_char hash[16];
54ca1c9b0cSelric   DES_key_schedule schedule;
556680b65dSchristos   EVP_CIPHER_CTX* des_ctx;
56ca1c9b0cSelric   DES_cblock deskey;
57ca1c9b0cSelric   DES_cblock zero;
58ca1c9b0cSelric   int32_t seq_number;
59ca1c9b0cSelric   size_t len, total_len;
60ca1c9b0cSelric 
61ca1c9b0cSelric   _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
62ca1c9b0cSelric 
63ca1c9b0cSelric   message_token->length = total_len;
64ca1c9b0cSelric   message_token->value  = malloc (total_len);
65ca1c9b0cSelric   if (message_token->value == NULL) {
66ca1c9b0cSelric     message_token->length = 0;
67ca1c9b0cSelric     *minor_status = ENOMEM;
68ca1c9b0cSelric     return GSS_S_FAILURE;
69ca1c9b0cSelric   }
70ca1c9b0cSelric 
71ca1c9b0cSelric   p = _gsskrb5_make_header(message_token->value,
72ca1c9b0cSelric 			      len,
73ca1c9b0cSelric 			      "\x01\x01", /* TOK_ID */
74ca1c9b0cSelric 			      GSS_KRB5_MECHANISM);
75ca1c9b0cSelric 
76ca1c9b0cSelric   memcpy (p, "\x00\x00", 2);	/* SGN_ALG = DES MAC MD5 */
77ca1c9b0cSelric   p += 2;
78ca1c9b0cSelric 
79ca1c9b0cSelric   memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */
80ca1c9b0cSelric   p += 4;
81ca1c9b0cSelric 
82ca1c9b0cSelric   /* Fill in later (SND-SEQ) */
83ca1c9b0cSelric   memset (p, 0, 16);
84ca1c9b0cSelric   p += 16;
85ca1c9b0cSelric 
86ca1c9b0cSelric   /* checksum */
87ca1c9b0cSelric   md5 = EVP_MD_CTX_create();
88ca1c9b0cSelric   EVP_DigestInit_ex(md5, EVP_md5(), NULL);
89ca1c9b0cSelric   EVP_DigestUpdate(md5, p - 24, 8);
90ca1c9b0cSelric   EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length);
91ca1c9b0cSelric   EVP_DigestFinal_ex(md5, hash, NULL);
92ca1c9b0cSelric   EVP_MD_CTX_destroy(md5);
93ca1c9b0cSelric 
94ca1c9b0cSelric   memset (&zero, 0, sizeof(zero));
95ca1c9b0cSelric   memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
96ca1c9b0cSelric   DES_set_key_unchecked (&deskey, &schedule);
97ca1c9b0cSelric   DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
98ca1c9b0cSelric 		 &schedule, &zero);
99ca1c9b0cSelric   memcpy (p - 8, hash, 8);	/* SGN_CKSUM */
100ca1c9b0cSelric 
101ca1c9b0cSelric   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
102ca1c9b0cSelric   /* sequence number */
103ca1c9b0cSelric   krb5_auth_con_getlocalseqnumber (context,
104ca1c9b0cSelric 				   ctx->auth_context,
105ca1c9b0cSelric 				   &seq_number);
106ca1c9b0cSelric 
107ca1c9b0cSelric   p -= 16;			/* SND_SEQ */
108ca1c9b0cSelric   p[0] = (seq_number >> 0)  & 0xFF;
109ca1c9b0cSelric   p[1] = (seq_number >> 8)  & 0xFF;
110ca1c9b0cSelric   p[2] = (seq_number >> 16) & 0xFF;
111ca1c9b0cSelric   p[3] = (seq_number >> 24) & 0xFF;
112ca1c9b0cSelric   memset (p + 4,
113ca1c9b0cSelric 	  (ctx->more_flags & LOCAL) ? 0 : 0xFF,
114ca1c9b0cSelric 	  4);
115ca1c9b0cSelric 
1166680b65dSchristos 
1176680b65dSchristos #if OPENSSL_VERSION_NUMBER < 0x10100000UL
1186680b65dSchristos   EVP_CIPHER_CTX des_ctxs;
1196680b65dSchristos   des_ctx = &des_ctxs;
1206680b65dSchristos   EVP_CIPHER_CTX_init(des_ctx);
1216680b65dSchristos #else
1226680b65dSchristos   des_ctx = EVP_CIPHER_CTX_new();
1236680b65dSchristos #endif
1246680b65dSchristos   EVP_CIPHER_CTX_init(des_ctx);
1257b2118deSchristos   if (!EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data,
1267b2118deSchristos       p + 8, 1)) {
1277b2118deSchristos       *minor_status = EINVAL;
1287b2118deSchristos       return GSS_S_FAILURE;
1297b2118deSchristos   }
1306680b65dSchristos   EVP_Cipher(des_ctx, p, p, 8);
1316680b65dSchristos #if OPENSSL_VERSION_NUMBER < 0x10100000UL
1326680b65dSchristos   EVP_CIPHER_CTX_cleanup(des_ctx);
1336680b65dSchristos #else
1346680b65dSchristos   EVP_CIPHER_CTX_free(des_ctx);
1356680b65dSchristos #endif
136ca1c9b0cSelric 
137ca1c9b0cSelric   krb5_auth_con_setlocalseqnumber (context,
138ca1c9b0cSelric 			       ctx->auth_context,
139ca1c9b0cSelric 			       ++seq_number);
140ca1c9b0cSelric   HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
141ca1c9b0cSelric 
142241bea01Schristos   memset_s(deskey, sizeof(deskey), 0, sizeof(deskey));
143241bea01Schristos   memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule));
144ca1c9b0cSelric 
145ca1c9b0cSelric   *minor_status = 0;
146ca1c9b0cSelric   return GSS_S_COMPLETE;
147ca1c9b0cSelric }
148ca1c9b0cSelric #endif
149ca1c9b0cSelric 
150ca1c9b0cSelric static OM_uint32
mic_des3(OM_uint32 * minor_status,const gsskrb5_ctx ctx,krb5_context context,gss_qop_t qop_req,const gss_buffer_t message_buffer,gss_buffer_t message_token,krb5_keyblock * key)151ca1c9b0cSelric mic_des3
152ca1c9b0cSelric            (OM_uint32 * minor_status,
153ca1c9b0cSelric             const gsskrb5_ctx ctx,
154ca1c9b0cSelric 	    krb5_context context,
155ca1c9b0cSelric             gss_qop_t qop_req,
156ca1c9b0cSelric             const gss_buffer_t message_buffer,
157ca1c9b0cSelric             gss_buffer_t message_token,
158ca1c9b0cSelric 	    krb5_keyblock *key
159ca1c9b0cSelric            )
160ca1c9b0cSelric {
161ca1c9b0cSelric   u_char *p;
162ca1c9b0cSelric   Checksum cksum;
163ca1c9b0cSelric   u_char seq[8];
164ca1c9b0cSelric 
165ca1c9b0cSelric   int32_t seq_number;
166ca1c9b0cSelric   size_t len, total_len;
167ca1c9b0cSelric 
168ca1c9b0cSelric   krb5_crypto crypto;
169ca1c9b0cSelric   krb5_error_code kret;
170ca1c9b0cSelric   krb5_data encdata;
171ca1c9b0cSelric   char *tmp;
172ca1c9b0cSelric   char ivec[8];
173ca1c9b0cSelric 
174ca1c9b0cSelric   _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM);
175ca1c9b0cSelric 
176ca1c9b0cSelric   message_token->length = total_len;
177ca1c9b0cSelric   message_token->value  = malloc (total_len);
178ca1c9b0cSelric   if (message_token->value == NULL) {
179ca1c9b0cSelric       message_token->length = 0;
180ca1c9b0cSelric       *minor_status = ENOMEM;
181ca1c9b0cSelric       return GSS_S_FAILURE;
182ca1c9b0cSelric   }
183ca1c9b0cSelric 
184ca1c9b0cSelric   p = _gsskrb5_make_header(message_token->value,
185ca1c9b0cSelric 			      len,
186ca1c9b0cSelric 			      "\x01\x01", /* TOK-ID */
187ca1c9b0cSelric 			      GSS_KRB5_MECHANISM);
188ca1c9b0cSelric 
189ca1c9b0cSelric   memcpy (p, "\x04\x00", 2);	/* SGN_ALG = HMAC SHA1 DES3-KD */
190ca1c9b0cSelric   p += 2;
191ca1c9b0cSelric 
192ca1c9b0cSelric   memcpy (p, "\xff\xff\xff\xff", 4); /* filler */
193ca1c9b0cSelric   p += 4;
194ca1c9b0cSelric 
195ca1c9b0cSelric   /* this should be done in parts */
196ca1c9b0cSelric 
197ca1c9b0cSelric   tmp = malloc (message_buffer->length + 8);
198ca1c9b0cSelric   if (tmp == NULL) {
199ca1c9b0cSelric       free (message_token->value);
200ca1c9b0cSelric       message_token->value = NULL;
201ca1c9b0cSelric       message_token->length = 0;
202ca1c9b0cSelric       *minor_status = ENOMEM;
203ca1c9b0cSelric       return GSS_S_FAILURE;
204ca1c9b0cSelric   }
205ca1c9b0cSelric   memcpy (tmp, p - 8, 8);
206ca1c9b0cSelric   memcpy (tmp + 8, message_buffer->value, message_buffer->length);
207ca1c9b0cSelric 
208ca1c9b0cSelric   kret = krb5_crypto_init(context, key, 0, &crypto);
209ca1c9b0cSelric   if (kret) {
210ca1c9b0cSelric       free (message_token->value);
211ca1c9b0cSelric       message_token->value = NULL;
212ca1c9b0cSelric       message_token->length = 0;
213ca1c9b0cSelric       free (tmp);
214ca1c9b0cSelric       *minor_status = kret;
215ca1c9b0cSelric       return GSS_S_FAILURE;
216ca1c9b0cSelric   }
217ca1c9b0cSelric 
218ca1c9b0cSelric   kret = krb5_create_checksum (context,
219ca1c9b0cSelric 			       crypto,
220ca1c9b0cSelric 			       KRB5_KU_USAGE_SIGN,
221ca1c9b0cSelric 			       0,
222ca1c9b0cSelric 			       tmp,
223ca1c9b0cSelric 			       message_buffer->length + 8,
224ca1c9b0cSelric 			       &cksum);
225ca1c9b0cSelric   free (tmp);
226ca1c9b0cSelric   krb5_crypto_destroy (context, crypto);
227ca1c9b0cSelric   if (kret) {
228ca1c9b0cSelric       free (message_token->value);
229ca1c9b0cSelric       message_token->value = NULL;
230ca1c9b0cSelric       message_token->length = 0;
231ca1c9b0cSelric       *minor_status = kret;
232ca1c9b0cSelric       return GSS_S_FAILURE;
233ca1c9b0cSelric   }
234ca1c9b0cSelric 
235ca1c9b0cSelric   memcpy (p + 8, cksum.checksum.data, cksum.checksum.length);
236ca1c9b0cSelric 
237ca1c9b0cSelric   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
238ca1c9b0cSelric   /* sequence number */
239ca1c9b0cSelric   krb5_auth_con_getlocalseqnumber (context,
240ca1c9b0cSelric 			       ctx->auth_context,
241ca1c9b0cSelric 			       &seq_number);
242ca1c9b0cSelric 
243ca1c9b0cSelric   seq[0] = (seq_number >> 0)  & 0xFF;
244ca1c9b0cSelric   seq[1] = (seq_number >> 8)  & 0xFF;
245ca1c9b0cSelric   seq[2] = (seq_number >> 16) & 0xFF;
246ca1c9b0cSelric   seq[3] = (seq_number >> 24) & 0xFF;
247ca1c9b0cSelric   memset (seq + 4,
248ca1c9b0cSelric 	  (ctx->more_flags & LOCAL) ? 0 : 0xFF,
249ca1c9b0cSelric 	  4);
250ca1c9b0cSelric 
251ca1c9b0cSelric   kret = krb5_crypto_init(context, key,
252ca1c9b0cSelric 			  ETYPE_DES3_CBC_NONE, &crypto);
253ca1c9b0cSelric   if (kret) {
254ca1c9b0cSelric       free (message_token->value);
255ca1c9b0cSelric       message_token->value = NULL;
256ca1c9b0cSelric       message_token->length = 0;
257ca1c9b0cSelric       *minor_status = kret;
258ca1c9b0cSelric       return GSS_S_FAILURE;
259ca1c9b0cSelric   }
260ca1c9b0cSelric 
261ca1c9b0cSelric   if (ctx->more_flags & COMPAT_OLD_DES3)
262ca1c9b0cSelric       memset(ivec, 0, 8);
263ca1c9b0cSelric   else
264ca1c9b0cSelric       memcpy(ivec, p + 8, 8);
265ca1c9b0cSelric 
266ca1c9b0cSelric   kret = krb5_encrypt_ivec (context,
267ca1c9b0cSelric 			    crypto,
268ca1c9b0cSelric 			    KRB5_KU_USAGE_SEQ,
269ca1c9b0cSelric 			    seq, 8, &encdata, ivec);
270ca1c9b0cSelric   krb5_crypto_destroy (context, crypto);
271ca1c9b0cSelric   if (kret) {
272ca1c9b0cSelric       free (message_token->value);
273ca1c9b0cSelric       message_token->value = NULL;
274ca1c9b0cSelric       message_token->length = 0;
275ca1c9b0cSelric       *minor_status = kret;
276ca1c9b0cSelric       return GSS_S_FAILURE;
277ca1c9b0cSelric   }
278ca1c9b0cSelric 
279ca1c9b0cSelric   assert (encdata.length == 8);
280ca1c9b0cSelric 
281ca1c9b0cSelric   memcpy (p, encdata.data, encdata.length);
282ca1c9b0cSelric   krb5_data_free (&encdata);
283ca1c9b0cSelric 
284ca1c9b0cSelric   krb5_auth_con_setlocalseqnumber (context,
285ca1c9b0cSelric 			       ctx->auth_context,
286ca1c9b0cSelric 			       ++seq_number);
287ca1c9b0cSelric   HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
288ca1c9b0cSelric 
289ca1c9b0cSelric   free_Checksum (&cksum);
290ca1c9b0cSelric   *minor_status = 0;
291ca1c9b0cSelric   return GSS_S_COMPLETE;
292ca1c9b0cSelric }
293ca1c9b0cSelric 
_gsskrb5_get_mic(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,gss_qop_t qop_req,const gss_buffer_t message_buffer,gss_buffer_t message_token)294ca1c9b0cSelric OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic
295ca1c9b0cSelric            (OM_uint32 * minor_status,
296b9d004c6Schristos             gss_const_ctx_id_t context_handle,
297ca1c9b0cSelric             gss_qop_t qop_req,
298ca1c9b0cSelric             const gss_buffer_t message_buffer,
299ca1c9b0cSelric             gss_buffer_t message_token
300ca1c9b0cSelric            )
301ca1c9b0cSelric {
302ca1c9b0cSelric   krb5_context context;
303ca1c9b0cSelric   const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
304ca1c9b0cSelric   krb5_keyblock *key;
305ca1c9b0cSelric   OM_uint32 ret;
306ca1c9b0cSelric 
307ca1c9b0cSelric   GSSAPI_KRB5_INIT (&context);
308ca1c9b0cSelric 
309ca1c9b0cSelric   if (ctx->more_flags & IS_CFX)
310ca1c9b0cSelric       return _gssapi_mic_cfx (minor_status, ctx, context, qop_req,
311ca1c9b0cSelric 			      message_buffer, message_token);
312ca1c9b0cSelric 
313ca1c9b0cSelric   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
314ca1c9b0cSelric   ret = _gsskrb5i_get_token_key(ctx, context, &key);
315ca1c9b0cSelric   HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
316ca1c9b0cSelric   if (ret) {
317ca1c9b0cSelric       *minor_status = ret;
318ca1c9b0cSelric       return GSS_S_FAILURE;
319ca1c9b0cSelric   }
320ca1c9b0cSelric 
321b9d004c6Schristos   switch (key->keytype) {
322b9d004c6Schristos   case KRB5_ENCTYPE_DES_CBC_CRC :
323b9d004c6Schristos   case KRB5_ENCTYPE_DES_CBC_MD4 :
324b9d004c6Schristos   case KRB5_ENCTYPE_DES_CBC_MD5 :
325ca1c9b0cSelric #ifdef HEIM_WEAK_CRYPTO
326ca1c9b0cSelric       ret = mic_des (minor_status, ctx, context, qop_req,
327ca1c9b0cSelric 		     message_buffer, message_token, key);
328ca1c9b0cSelric #else
329ca1c9b0cSelric       ret = GSS_S_FAILURE;
330ca1c9b0cSelric #endif
331ca1c9b0cSelric       break;
332b9d004c6Schristos   case KRB5_ENCTYPE_DES3_CBC_MD5 :
333b9d004c6Schristos   case KRB5_ENCTYPE_DES3_CBC_SHA1 :
334ca1c9b0cSelric       ret = mic_des3 (minor_status, ctx, context, qop_req,
335ca1c9b0cSelric 		      message_buffer, message_token, key);
336ca1c9b0cSelric       break;
337b9d004c6Schristos   case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5:
338b9d004c6Schristos   case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56:
339ca1c9b0cSelric       ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req,
340ca1c9b0cSelric 				     message_buffer, message_token, key);
341ca1c9b0cSelric       break;
342ca1c9b0cSelric   default :
343ca1c9b0cSelric       abort();
344ca1c9b0cSelric       break;
345ca1c9b0cSelric   }
346ca1c9b0cSelric   krb5_free_keyblock (context, key);
347ca1c9b0cSelric   return ret;
348ca1c9b0cSelric }
349