Remove building with NOCRYPTO option
[minix.git] / crypto / external / bsd / heimdal / dist / lib / gssapi / netlogon / crypto.c
blob0b28983ef83673f8191153da9026c88e3a0762db
1 /* $NetBSD: crypto.c,v 1.1.1.1 2011/04/13 18:14:47 elric Exp $ */
3 /*
4 * Copyright (c) 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
38 #include "netlogon.h"
40 static uint8_t zeros[4];
42 static void
43 _netlogon_encode_sequence_number(uint64_t SequenceNumber, uint8_t *p,
44 int initiatorFlag)
46 uint32_t LowPart, HighPart;
48 LowPart = (SequenceNumber >> 0 ) & 0xFFFFFFFF;
49 HighPart = (SequenceNumber >> 32) & 0xFFFFFFFF;
51 _gss_mg_encode_be_uint32(LowPart, &p[0]);
52 _gss_mg_encode_be_uint32(HighPart, &p[4]);
54 if (initiatorFlag)
55 p[4] |= 0x80;
58 static int
59 _netlogon_decode_sequence_number(void *ptr, uint64_t *n,
60 int initiatorFlag)
62 uint8_t *p = ptr;
63 uint32_t LowPart, HighPart;
64 int gotInitiatorFlag;
66 gotInitiatorFlag = (p[4] & 0x80) != 0;
67 if (gotInitiatorFlag != initiatorFlag)
68 return -1;
70 p[4] &= 0x7F; /* clear initiator bit */
72 _gss_mg_decode_be_uint32(&p[0], &LowPart);
73 _gss_mg_decode_be_uint32(&p[4], &HighPart);
75 *n = (LowPart << 0) | ((uint64_t)HighPart << 32);
77 return 0;
80 static inline size_t
81 _netlogon_checksum_length(NL_AUTH_SIGNATURE *sig)
83 #if 0
84 return (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) ? 32 : 8;
85 #else
86 /* Owing to a bug in Windows it always uses the old value */
87 return 8;
88 #endif
91 static inline size_t
92 _netlogon_signature_length(uint16_t alg, int conf_req_flag)
94 return NL_AUTH_SIGNATURE_COMMON_LENGTH +
95 (alg == NL_SIGN_ALG_SHA256 ? 32 : 8) +
96 (conf_req_flag ? 8 : 0);
99 static inline uint8_t *
100 _netlogon_confounder(NL_AUTH_SIGNATURE *sig)
102 size_t cksumlen = _netlogon_checksum_length(sig);
104 return &sig->Checksum[cksumlen];
107 static int
108 _netlogon_encode_NL_AUTH_SIGNATURE(NL_AUTH_SIGNATURE *sig,
109 uint8_t *p, size_t len)
111 *p++ = (sig->SignatureAlgorithm >> 0) & 0xFF;
112 *p++ = (sig->SignatureAlgorithm >> 8) & 0xFF;
113 *p++ = (sig->SealAlgorithm >> 0) & 0xFF;
114 *p++ = (sig->SealAlgorithm >> 8) & 0xFF;
115 *p++ = (sig->Pad >> 0) & 0xFF;
116 *p++ = (sig->Pad >> 8) & 0xFF;
117 *p++ = (sig->Flags >> 0) & 0xFF;
118 *p++ = (sig->Flags >> 8) & 0xFF;
120 if (len > NL_AUTH_SIGNATURE_HEADER_LENGTH) {
121 memcpy(p, sig->SequenceNumber, 8);
122 p += 8;
125 if (len > NL_AUTH_SIGNATURE_COMMON_LENGTH) {
126 size_t cksumlen = _netlogon_checksum_length(sig);
128 memcpy(p, sig->Checksum, cksumlen);
129 p += cksumlen;
131 /* Confounder, if present, is immediately after checksum */
132 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) {
133 memcpy(p, &sig->Checksum[cksumlen], 8);
137 return 0;
140 static int
141 _netlogon_decode_NL_AUTH_SIGNATURE(const uint8_t *ptr,
142 size_t len,
143 NL_AUTH_SIGNATURE *sig)
145 const uint8_t *p = ptr;
146 size_t cksumlen;
148 if (len < NL_AUTH_SIGNATURE_COMMON_LENGTH)
149 return KRB5_BAD_MSIZE;
151 sig->SignatureAlgorithm = (p[0] << 0) | (p[1] << 8);
152 sig->SealAlgorithm = (p[2] << 0) | (p[3] << 8);
153 sig->Pad = (p[4] << 0) | (p[5] << 8);
154 sig->Flags = (p[6] << 0) | (p[7] << 8);
155 p += 8;
157 memcpy(sig->SequenceNumber, p, 8);
158 p += 8;
160 /* Validate signature algorithm is known and matches enctype */
161 switch (sig->SignatureAlgorithm) {
162 case NL_SIGN_ALG_HMAC_MD5:
163 cksumlen = NL_AUTH_SIGNATURE_LENGTH;
164 break;
165 case NL_SIGN_ALG_SHA256:
166 cksumlen = NL_AUTH_SHA2_SIGNATURE_LENGTH;
167 break;
168 default:
169 return EINVAL;
170 break;
173 if (sig->SealAlgorithm == NL_SEAL_ALG_NONE)
174 cksumlen -= 8; /* confounder is optional if no sealing */
176 if (len < cksumlen)
177 return KRB5_BAD_MSIZE;
179 /* Copy variable length checksum */
180 cksumlen = _netlogon_checksum_length(sig);
181 memcpy(sig->Checksum, p, cksumlen);
182 p += cksumlen;
184 /* Copy confounder in past checksum */
185 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE)
186 memcpy(&sig->Checksum[cksumlen], p, 8);
188 return 0;
191 static void
192 _netlogon_derive_rc4_hmac_key(uint8_t key[16],
193 uint8_t *salt,
194 size_t saltLength,
195 EVP_CIPHER_CTX *rc4Key,
196 int enc)
198 uint8_t tmpData[MD5_DIGEST_LENGTH];
199 uint8_t derivedKey[MD5_DIGEST_LENGTH];
200 unsigned int len = MD5_DIGEST_LENGTH;
202 HMAC(EVP_md5(), key, 16, zeros, sizeof(zeros), tmpData, &len);
203 HMAC(EVP_md5(), tmpData, MD5_DIGEST_LENGTH,
204 salt, saltLength, derivedKey, &len);
206 assert(len == MD5_DIGEST_LENGTH);
208 EVP_CipherInit_ex(rc4Key, EVP_rc4(), NULL, derivedKey, NULL, enc);
210 memset(derivedKey, 0, sizeof(derivedKey));
213 static void
214 _netlogon_derive_rc4_seal_key(gssnetlogon_ctx ctx,
215 NL_AUTH_SIGNATURE *sig,
216 EVP_CIPHER_CTX *sealkey,
217 int enc)
219 uint8_t xorKey[16];
220 int i;
222 for (i = 0; i < sizeof(xorKey); i++) {
223 xorKey[i] = ctx->SessionKey[i] ^ 0xF0;
226 _netlogon_derive_rc4_hmac_key(xorKey,
227 sig->SequenceNumber, sizeof(sig->SequenceNumber), sealkey, enc);
229 memset(xorKey, 0, sizeof(xorKey));
232 static void
233 _netlogon_derive_rc4_seq_key(gssnetlogon_ctx ctx,
234 NL_AUTH_SIGNATURE *sig,
235 EVP_CIPHER_CTX *seqkey,
236 int enc)
238 _netlogon_derive_rc4_hmac_key(ctx->SessionKey,
239 sig->Checksum, sizeof(sig->Checksum), seqkey, enc);
242 static void
243 _netlogon_derive_aes_seal_key(gssnetlogon_ctx ctx,
244 NL_AUTH_SIGNATURE *sig,
245 EVP_CIPHER_CTX *sealkey,
246 int enc)
248 uint8_t encryptionKey[16];
249 uint8_t ivec[16];
250 int i;
252 for (i = 0; i < sizeof(encryptionKey); i++) {
253 encryptionKey[i] = ctx->SessionKey[i] ^ 0xF0;
256 memcpy(&ivec[0], sig->SequenceNumber, 8);
257 memcpy(&ivec[8], sig->SequenceNumber, 8);
259 EVP_CipherInit_ex(sealkey, EVP_aes_128_cfb8(),
260 NULL, encryptionKey, ivec, enc);
262 memset(encryptionKey, 0, sizeof(encryptionKey));
265 static void
266 _netlogon_derive_aes_seq_key(gssnetlogon_ctx ctx,
267 NL_AUTH_SIGNATURE *sig,
268 EVP_CIPHER_CTX *seqkey,
269 int enc)
271 uint8_t ivec[16];
273 memcpy(&ivec[0], sig->Checksum, 8);
274 memcpy(&ivec[8], sig->Checksum, 8);
276 EVP_CipherInit_ex(seqkey, EVP_aes_128_cfb8(),
277 NULL, ctx->SessionKey, ivec, enc);
280 static void
281 _netlogon_seal(gssnetlogon_ctx ctx,
282 NL_AUTH_SIGNATURE *sig,
283 gss_iov_buffer_desc *iov,
284 int iov_count,
285 int enc)
287 EVP_CIPHER_CTX sealkey;
288 int i;
289 uint8_t *confounder = _netlogon_confounder(sig);
291 EVP_CIPHER_CTX_init(&sealkey);
293 if (sig->SealAlgorithm == NL_SEAL_ALG_AES128)
294 _netlogon_derive_aes_seal_key(ctx, sig, &sealkey, enc);
295 else
296 _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc);
298 EVP_Cipher(&sealkey, confounder, confounder, 8);
301 * For RC4, Windows resets the cipherstate after encrypting
302 * the confounder, thus defeating the purpose of the confounder
304 if (sig->SealAlgorithm == NL_SEAL_ALG_RC4) {
305 EVP_CipherFinal_ex(&sealkey, NULL, &i);
306 _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc);
309 for (i = 0; i < iov_count; i++) {
310 gss_iov_buffer_t iovp = &iov[i];
312 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) {
313 case GSS_IOV_BUFFER_TYPE_DATA:
314 case GSS_IOV_BUFFER_TYPE_PADDING:
315 EVP_Cipher(&sealkey, iovp->buffer.value, iovp->buffer.value,
316 iovp->buffer.length);
317 break;
318 default:
319 break;
323 EVP_CipherFinal_ex(&sealkey, NULL, &i);
324 EVP_CIPHER_CTX_cleanup(&sealkey);
327 static void
328 _netlogon_seq(gssnetlogon_ctx ctx,
329 NL_AUTH_SIGNATURE *sig,
330 int enc)
332 EVP_CIPHER_CTX seqkey;
334 EVP_CIPHER_CTX_init(&seqkey);
336 if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256)
337 _netlogon_derive_aes_seq_key(ctx, sig, &seqkey, enc);
338 else
339 _netlogon_derive_rc4_seq_key(ctx, sig, &seqkey, enc);
341 EVP_Cipher(&seqkey, sig->SequenceNumber, sig->SequenceNumber, 8);
343 EVP_CIPHER_CTX_cleanup(&seqkey);
346 static void
347 _netlogon_digest_md5(gssnetlogon_ctx ctx,
348 NL_AUTH_SIGNATURE *sig,
349 gss_iov_buffer_desc *iov,
350 int iov_count,
351 uint8_t *md)
353 EVP_MD_CTX *md5;
354 uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH];
355 uint8_t digest[MD5_DIGEST_LENGTH];
356 unsigned int md_len = MD5_DIGEST_LENGTH;
357 int i;
359 _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header));
361 md5 = EVP_MD_CTX_create();
362 EVP_DigestInit_ex(md5, EVP_md5(), NULL);
363 EVP_DigestUpdate(md5, zeros, sizeof(zeros));
364 EVP_DigestUpdate(md5, header, sizeof(header));
366 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) {
367 EVP_DigestUpdate(md5, sig->Confounder, sizeof(sig->Confounder));
370 for (i = 0; i < iov_count; i++) {
371 gss_iov_buffer_t iovp = &iov[i];
373 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) {
374 case GSS_IOV_BUFFER_TYPE_DATA:
375 case GSS_IOV_BUFFER_TYPE_PADDING:
376 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
377 EVP_DigestUpdate(md5, iovp->buffer.value, iovp->buffer.length);
378 break;
379 default:
380 break;
384 EVP_DigestFinal_ex(md5, digest, NULL);
385 EVP_MD_CTX_destroy(md5);
387 HMAC(EVP_md5(), ctx->SessionKey, sizeof(ctx->SessionKey),
388 digest, sizeof(digest), digest, &md_len);
389 memcpy(md, digest, 8);
392 static void
393 _netlogon_digest_sha256(gssnetlogon_ctx ctx,
394 NL_AUTH_SIGNATURE *sig,
395 gss_iov_buffer_desc *iov,
396 int iov_count,
397 uint8_t *md)
399 HMAC_CTX hmac;
400 uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH];
401 uint8_t digest[SHA256_DIGEST_LENGTH];
402 unsigned int md_len = SHA256_DIGEST_LENGTH;
403 int i;
405 /* Encode first 8 bytes of signature into header */
406 _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header));
408 HMAC_CTX_init(&hmac);
409 HMAC_Init_ex(&hmac, ctx->SessionKey, sizeof(ctx->SessionKey),
410 EVP_sha256(), NULL);
411 HMAC_Update(&hmac, header, sizeof(header));
413 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) {
415 * If the checksum length bug is ever fixed, then be sure to
416 * update this code to point to &sig->Checksum[32] as that is
417 * where the confounder is supposed to be.
419 HMAC_Update(&hmac, sig->Confounder, 8);
422 for (i = 0; i < iov_count; i++) {
423 gss_iov_buffer_t iovp = &iov[i];
425 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) {
426 case GSS_IOV_BUFFER_TYPE_DATA:
427 case GSS_IOV_BUFFER_TYPE_PADDING:
428 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
429 HMAC_Update(&hmac, iovp->buffer.value, iovp->buffer.length);
430 break;
431 default:
432 break;
436 HMAC_Final(&hmac, digest, &md_len);
437 HMAC_CTX_cleanup(&hmac);
438 memcpy(md, digest, 8);
441 static void
442 _netlogon_digest(gssnetlogon_ctx ctx,
443 NL_AUTH_SIGNATURE *sig,
444 gss_iov_buffer_desc *iov,
445 int iov_count,
446 uint8_t *md)
448 if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256)
449 _netlogon_digest_sha256(ctx, sig, iov, iov_count, md);
450 else
451 _netlogon_digest_md5(ctx, sig, iov, iov_count, md);
454 OM_uint32
455 _netlogon_wrap_iov(OM_uint32 * minor_status,
456 gss_ctx_id_t context_handle,
457 int conf_req_flag,
458 gss_qop_t qop_req,
459 int *conf_state,
460 gss_iov_buffer_desc *iov,
461 int iov_count)
463 OM_uint32 ret;
464 gss_iov_buffer_t header;
465 NL_AUTH_SIGNATURE_U sigbuf = { { 0 } };
466 NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf);
467 gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle;
468 size_t size;
469 uint8_t *seqdata;
471 if (ctx->State != NL_AUTH_ESTABLISHED) {
472 *minor_status = EINVAL;
473 return GSS_S_FAILURE;
476 header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
477 if (header == NULL) {
478 *minor_status = EINVAL;
479 return GSS_S_FAILURE;
482 size = _netlogon_signature_length(ctx->SignatureAlgorithm, conf_req_flag);
484 if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
485 ret = _gss_mg_allocate_buffer(minor_status, header, size);
486 if (GSS_ERROR(ret))
487 return ret;
488 } else if (header->buffer.length < size) {
489 *minor_status = KRB5_BAD_MSIZE;
490 return GSS_S_FAILURE;
491 } else {
492 header->buffer.length = size;
495 memset(header->buffer.value, 0, header->buffer.length);
497 sig->SignatureAlgorithm = ctx->SignatureAlgorithm;
498 sig->SealAlgorithm = conf_req_flag ? ctx->SealAlgorithm : NL_SEAL_ALG_NONE;
500 if (conf_req_flag)
501 krb5_generate_random_block(_netlogon_confounder(sig), 8);
503 sig->Pad = 0xFFFF; /* [MS-NRPC] 3.3.4.2.1.3 */
504 sig->Flags = 0; /* [MS-NRPC] 3.3.4.2.1.4 */
505 HEIMDAL_MUTEX_lock(&ctx->Mutex);
506 _netlogon_encode_sequence_number(ctx->SequenceNumber, sig->SequenceNumber,
507 ctx->LocallyInitiated);
508 ctx->SequenceNumber++;
509 HEIMDAL_MUTEX_unlock(&ctx->Mutex);
511 /* [MS-NRPC] 3.3.4.2.1.7: sign header, optional confounder and data */
512 _netlogon_digest(ctx, sig, iov, iov_count, sig->Checksum);
514 /* [MS-NRPC] 3.3.4.2.1.8: optionally encrypt confounder and data */
515 if (conf_req_flag)
516 _netlogon_seal(ctx, sig, iov, iov_count, 1);
518 /* [MS-NRPC] 3.3.4.2.1.9: encrypt sequence number */
519 _netlogon_seq(ctx, sig, 1);
521 _netlogon_encode_NL_AUTH_SIGNATURE(sig, header->buffer.value,
522 header->buffer.length);
524 if (conf_state != NULL)
525 *conf_state = conf_req_flag;
527 *minor_status = 0;
528 return GSS_S_COMPLETE;
531 OM_uint32
532 _netlogon_unwrap_iov(OM_uint32 *minor_status,
533 gss_ctx_id_t context_handle,
534 int *conf_state,
535 gss_qop_t *qop_state,
536 gss_iov_buffer_desc *iov,
537 int iov_count)
539 OM_uint32 ret;
540 gss_iov_buffer_t header;
541 NL_AUTH_SIGNATURE_U sigbuf;
542 NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf);
543 gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle;
544 uint8_t checksum[SHA256_DIGEST_LENGTH];
545 uint64_t SequenceNumber;
547 if (ctx->State != NL_AUTH_ESTABLISHED) {
548 *minor_status = EINVAL;
549 return GSS_S_FAILURE;
552 header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
553 if (header == NULL) {
554 *minor_status = EINVAL;
555 return GSS_S_FAILURE;
558 ret = _netlogon_decode_NL_AUTH_SIGNATURE(header->buffer.value,
559 header->buffer.length,
560 sig);
561 if (ret != 0) {
562 *minor_status = ret;
563 return GSS_S_DEFECTIVE_TOKEN;
566 /* [MS-NRPC] 3.3.4.2.2.1: verify signature algorithm selection */
567 if (sig->SignatureAlgorithm != ctx->SignatureAlgorithm)
568 return GSS_S_BAD_SIG;
570 /* [MS-NRPC] 3.3.4.2.2.2: verify encryption algorithm selection */
571 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE &&
572 sig->SealAlgorithm != ctx->SealAlgorithm)
573 return GSS_S_DEFECTIVE_TOKEN;
575 /* [MS-NRPC] 3.3.4.2.2.3: verify Pad bytes */
576 if (sig->Pad != 0xFFFF)
577 return GSS_S_DEFECTIVE_TOKEN;
579 /* [MS-NRPC] 3.3.4.2.2.5: decrypt sequence number */
580 _netlogon_seq(ctx, sig, 0);
582 /* [MS-NRPC] 3.3.4.2.2.6: decode sequence number */
583 if (_netlogon_decode_sequence_number(sig->SequenceNumber, &SequenceNumber,
584 !ctx->LocallyInitiated) != 0)
585 return GSS_S_UNSEQ_TOKEN;
587 /* [MS-NRPC] 3.3.4.2.2.9: decrypt confounder and data */
588 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE)
589 _netlogon_seal(ctx, sig, iov, iov_count, 0);
591 /* [MS-NRPC] 3.3.4.2.2.10: verify signature */
592 _netlogon_digest(ctx, sig, iov, iov_count, checksum);
593 if (memcmp(sig->Checksum, checksum, _netlogon_checksum_length(sig)) != 0)
594 return GSS_S_BAD_SIG;
596 HEIMDAL_MUTEX_lock(&ctx->Mutex);
597 if (SequenceNumber != ctx->SequenceNumber) {
598 /* [MS-NRPC] 3.3.4.2.2.7: check sequence number */
599 ret = GSS_S_UNSEQ_TOKEN;
600 } else {
601 /* [MS-NRPC] 3.3.4.2.2.8: increment sequence number */
602 ctx->SequenceNumber++;
603 ret = GSS_S_COMPLETE;
605 HEIMDAL_MUTEX_unlock(&ctx->Mutex);
607 if (conf_state != NULL)
608 *conf_state = (sig->SealAlgorithm != NL_SEAL_ALG_NONE);
609 if (qop_state != NULL)
610 *qop_state = GSS_C_QOP_DEFAULT;
612 *minor_status = 0;
613 return ret;
616 OM_uint32
617 _netlogon_wrap_iov_length(OM_uint32 * minor_status,
618 gss_ctx_id_t context_handle,
619 int conf_req_flag,
620 gss_qop_t qop_req,
621 int *conf_state,
622 gss_iov_buffer_desc *iov,
623 int iov_count)
625 OM_uint32 ret;
626 gss_iov_buffer_t iovp;
627 gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle;
628 size_t len;
630 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
631 if (iovp == NULL) {
632 *minor_status = EINVAL;
633 return GSS_S_FAILURE;
636 len = NL_AUTH_SIGNATURE_COMMON_LENGTH;
637 if (ctx->SignatureAlgorithm == NL_SIGN_ALG_SHA256)
638 len += 32; /* SHA2 checksum size */
639 else
640 len += 8; /* HMAC checksum size */
641 if (conf_req_flag)
642 len += 8; /* counfounder */
644 iovp->buffer.length = len;
646 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
647 if (iovp != NULL)
648 iovp->buffer.length = 0;
650 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
651 if (iovp != NULL)
652 iovp->buffer.length = 0;
654 if (conf_state != NULL)
655 *conf_state = conf_req_flag;
657 *minor_status = 0;
658 return GSS_S_COMPLETE;
661 OM_uint32 _netlogon_get_mic
662 (OM_uint32 * minor_status,
663 const gss_ctx_id_t context_handle,
664 gss_qop_t qop_req,
665 const gss_buffer_t message_buffer,
666 gss_buffer_t message_token
669 gss_iov_buffer_desc iov[2];
670 OM_uint32 ret;
672 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
673 iov[0].buffer = *message_buffer;
674 iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
675 iov[1].buffer.length = 0;
676 iov[1].buffer.value = NULL;
678 ret = _netlogon_wrap_iov(minor_status, context_handle, 0,
679 qop_req, NULL, iov, 2);
680 if (ret == GSS_S_COMPLETE)
681 *message_token = iov[1].buffer;
683 return ret;
686 OM_uint32
687 _netlogon_verify_mic
688 (OM_uint32 * minor_status,
689 const gss_ctx_id_t context_handle,
690 const gss_buffer_t message_buffer,
691 const gss_buffer_t token_buffer,
692 gss_qop_t * qop_state
695 gss_iov_buffer_desc iov[2];
697 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
698 iov[0].buffer = *message_buffer;
699 iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
700 iov[1].buffer = *token_buffer;
702 return _netlogon_unwrap_iov(minor_status, context_handle,
703 NULL, qop_state, iov, 2);
706 OM_uint32
707 _netlogon_wrap_size_limit (
708 OM_uint32 * minor_status,
709 const gss_ctx_id_t context_handle,
710 int conf_req_flag,
711 gss_qop_t qop_req,
712 OM_uint32 req_output_size,
713 OM_uint32 *max_input_size
716 gss_iov_buffer_desc iov[1];
717 OM_uint32 ret;
719 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
720 iov[0].buffer.length = 0;
722 ret = _netlogon_wrap_iov_length(minor_status, context_handle,
723 conf_req_flag, qop_req, NULL,
724 iov, sizeof(iov)/sizeof(iov[0]));
725 if (GSS_ERROR(ret))
726 return ret;
728 if (req_output_size < iov[0].buffer.length)
729 *max_input_size = 0;
730 else
731 *max_input_size = req_output_size - iov[0].buffer.length;
733 return GSS_S_COMPLETE;