1/*
2 * Copyright (c) 1997 - 2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
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.
16 *
17 * 3. Neither the name of the Institute 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.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#define HC_DEPRECATED_CRYPTO
35
36#include "mech_locl.h"
37
38#include <krb5.h>
39#include <roken.h>
40
41#include "crypto-headers.h"
42
43
44OM_uint32
45gss_mg_gen_cb(OM_uint32 *minor_status,
46	      const gss_channel_bindings_t b,
47	      uint8_t p[16], gss_buffer_t buffer)
48{
49    krb5_error_code ret;
50    krb5_ssize_t sret;
51    krb5_storage *sp;
52    krb5_data data;
53
54    krb5_data_zero(&data);
55
56    sp = krb5_storage_emem();
57    if (sp == NULL) {
58	*minor_status = ENOMEM;
59	goto out;
60    }
61    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
62
63    ret = krb5_store_uint32(sp, b->initiator_addrtype);
64    if (ret) {
65	*minor_status = ret;
66	goto out;
67    }
68    ret = krb5_store_uint32(sp, (uint32_t)b->initiator_address.length);
69    if (ret) {
70	*minor_status = ret;
71	goto out;
72    }
73    sret = krb5_storage_write(sp, b->initiator_address.value,
74			     (uint32_t)b->initiator_address.length);
75    if (sret < 0 || (size_t)sret != b->initiator_address.length) {
76	*minor_status = ENOMEM;
77	goto out;
78    }
79
80    ret = krb5_store_uint32(sp, b->acceptor_addrtype);
81    if (ret) {
82	*minor_status = ret;
83	goto out;
84    }
85    ret = krb5_store_uint32(sp, (uint32_t)b->acceptor_address.length);
86    if (ret) {
87	*minor_status = ret;
88	goto out;
89    }
90    sret = krb5_storage_write(sp, b->acceptor_address.value,
91			     b->acceptor_address.length);
92    if (sret < 0 || (size_t)sret != b->acceptor_address.length) {
93	*minor_status = ENOMEM;
94	goto out;
95    }
96
97    ret = krb5_store_uint32(sp, (uint32_t)b->application_data.length);
98    if (ret) {
99	*minor_status = ret;
100	goto out;
101    }
102    sret = krb5_storage_write(sp, b->application_data.value,
103			      b->application_data.length);
104    if (sret < 0 || (size_t)sret != b->application_data.length) {
105	*minor_status = ENOMEM;
106	goto out;
107    }
108
109    ret = krb5_storage_to_data(sp, &data);
110    if (ret) {
111	*minor_status = ret;
112	goto out;
113    }
114
115    CCDigest(kCCDigestMD5, data.data, data.length, p);
116
117    if (buffer) {
118	buffer->value = data.data;
119	buffer->length = data.length;
120    } else {
121	krb5_data_free(&data);
122    }
123
124    *minor_status = 0;
125    return GSS_S_COMPLETE;
126
127 out:
128    if (sp)
129	krb5_storage_free(sp);
130    return GSS_S_FAILURE;
131}
132
133OM_uint32
134gss_mg_validate_cb(OM_uint32 *minor_status,
135		   const gss_channel_bindings_t b,
136		   const uint8_t p[16],
137		   gss_buffer_t buffer)
138{
139    static uint8_t zeros[16] = { 0 };
140    OM_uint32 major_status, junk;
141    uint8_t hash[16];
142
143    if (b != GSS_C_NO_CHANNEL_BINDINGS
144	&& memcmp(p, zeros, sizeof(zeros)) != 0) {
145
146	major_status = gss_mg_gen_cb(minor_status, b, hash, buffer);
147	if (major_status)
148	    return major_status;
149
150	if(ct_memcmp(hash, p, sizeof(hash)) != 0) {
151	    gss_release_buffer(&junk, buffer);
152	    *minor_status = 0;
153	    return GSS_S_BAD_BINDINGS;
154	}
155    } else {
156	buffer->length = 0;
157	buffer->value = NULL;
158    }
159
160    return GSS_S_COMPLETE;
161}
162