1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * token.c
24*7c478bd9Sstevel@tonic-gate *
25*7c478bd9Sstevel@tonic-gate * Copyright (c) 1997, by Sun Microsystems, Inc.
26*7c478bd9Sstevel@tonic-gate * All rights reserved.
27*7c478bd9Sstevel@tonic-gate *
28*7c478bd9Sstevel@tonic-gate */
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate #include <stdio.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include <string.h>
33*7c478bd9Sstevel@tonic-gate
34*7c478bd9Sstevel@tonic-gate #include "dh_gssapi.h"
35*7c478bd9Sstevel@tonic-gate #include "crypto.h"
36*7c478bd9Sstevel@tonic-gate
37*7c478bd9Sstevel@tonic-gate extern int
38*7c478bd9Sstevel@tonic-gate get_der_length(unsigned char **, unsigned int, unsigned int *);
39*7c478bd9Sstevel@tonic-gate
40*7c478bd9Sstevel@tonic-gate extern unsigned int
41*7c478bd9Sstevel@tonic-gate der_length_size(unsigned int);
42*7c478bd9Sstevel@tonic-gate
43*7c478bd9Sstevel@tonic-gate extern int
44*7c478bd9Sstevel@tonic-gate put_der_length(unsigned int, unsigned char **, unsigned int);
45*7c478bd9Sstevel@tonic-gate
46*7c478bd9Sstevel@tonic-gate #define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */
47*7c478bd9Sstevel@tonic-gate
48*7c478bd9Sstevel@tonic-gate static OM_uint32
49*7c478bd9Sstevel@tonic-gate __xdr_encode_token(XDR *, gss_buffer_t, dh_token_t, dh_key_set_t);
50*7c478bd9Sstevel@tonic-gate
51*7c478bd9Sstevel@tonic-gate static OM_uint32
52*7c478bd9Sstevel@tonic-gate __xdr_decode_token(XDR *, gss_buffer_t,
53*7c478bd9Sstevel@tonic-gate dh_token_t, dh_key_set_t, dh_signature_t);
54*7c478bd9Sstevel@tonic-gate
55*7c478bd9Sstevel@tonic-gate /*
56*7c478bd9Sstevel@tonic-gate * get_qop: For a Diffie-Hellman token_t, return the associate QOP
57*7c478bd9Sstevel@tonic-gate */
58*7c478bd9Sstevel@tonic-gate static dh_qop_t
get_qop(dh_token_t t)59*7c478bd9Sstevel@tonic-gate get_qop(dh_token_t t)
60*7c478bd9Sstevel@tonic-gate {
61*7c478bd9Sstevel@tonic-gate dh_token_body_t body = &t->ver.dh_version_u.body;
62*7c478bd9Sstevel@tonic-gate switch (body->type) {
63*7c478bd9Sstevel@tonic-gate case DH_INIT_CNTX:
64*7c478bd9Sstevel@tonic-gate case DH_ACCEPT_CNTX:
65*7c478bd9Sstevel@tonic-gate return (DH_MECH_QOP);
66*7c478bd9Sstevel@tonic-gate case DH_MIC:
67*7c478bd9Sstevel@tonic-gate return (body->dh_token_body_desc_u.sign.qop);
68*7c478bd9Sstevel@tonic-gate case DH_WRAP:
69*7c478bd9Sstevel@tonic-gate return (body->dh_token_body_desc_u.seal.mic.qop);
70*7c478bd9Sstevel@tonic-gate default:
71*7c478bd9Sstevel@tonic-gate /* Should never get here */
72*7c478bd9Sstevel@tonic-gate return (DH_MECH_QOP);
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate }
75*7c478bd9Sstevel@tonic-gate
76*7c478bd9Sstevel@tonic-gate /*
77*7c478bd9Sstevel@tonic-gate * __make_ap_token: This routine generates a Diffie-Hellman serialized
78*7c478bd9Sstevel@tonic-gate * token which has an ASN.1 application 0 header prepended. The unserialized
79*7c478bd9Sstevel@tonic-gate * token supplied should be of type DH_INIT_CNTX.
80*7c478bd9Sstevel@tonic-gate *
81*7c478bd9Sstevel@tonic-gate * The ASN.1 applicationtion prefix is encoded as follows:
82*7c478bd9Sstevel@tonic-gate *
83*7c478bd9Sstevel@tonic-gate * +------+
84*7c478bd9Sstevel@tonic-gate * | 0x60 | 1 TAG for APPLICATION 0
85*7c478bd9Sstevel@tonic-gate * +------+
86*7c478bd9Sstevel@tonic-gate * | |
87*7c478bd9Sstevel@tonic-gate * ~ ~ app_size DER encoded length of oid_size + token_size
88*7c478bd9Sstevel@tonic-gate * | |
89*7c478bd9Sstevel@tonic-gate * +------+
90*7c478bd9Sstevel@tonic-gate * | 0x06 | 1 TAG for OID
91*7c478bd9Sstevel@tonic-gate * +------+
92*7c478bd9Sstevel@tonic-gate * | | der_length_size
93*7c478bd9Sstevel@tonic-gate * ~ ~ (mech->length) DER encoded length of mech->length
94*7c478bd9Sstevel@tonic-gate * | |
95*7c478bd9Sstevel@tonic-gate * +------+
96*7c478bd9Sstevel@tonic-gate * | |
97*7c478bd9Sstevel@tonic-gate * ~ ~ mech->length OID elements (mech->elements)
98*7c478bd9Sstevel@tonic-gate * | |
99*7c478bd9Sstevel@tonic-gate * +------+
100*7c478bd9Sstevel@tonic-gate * | 0x00 | 0-3 XDR padding
101*7c478bd9Sstevel@tonic-gate * +------+
102*7c478bd9Sstevel@tonic-gate * | |
103*7c478bd9Sstevel@tonic-gate * ~ ~ Serialized DH token
104*7c478bd9Sstevel@tonic-gate * | |
105*7c478bd9Sstevel@tonic-gate * +------+
106*7c478bd9Sstevel@tonic-gate * | 0x00 | 0-3 Left over XDR padding
107*7c478bd9Sstevel@tonic-gate * +------+
108*7c478bd9Sstevel@tonic-gate *
109*7c478bd9Sstevel@tonic-gate * We will define the token_size to be the sizeof the serialize token plus
110*7c478bd9Sstevel@tonic-gate * 3 the maximum XDR paddinging that will be needed. Thus the XDR padding
111*7c478bd9Sstevel@tonic-gate * plus the left over XDR padding will alway equal 3.
112*7c478bd9Sstevel@tonic-gate */
113*7c478bd9Sstevel@tonic-gate OM_uint32
__make_ap_token(gss_buffer_t result,gss_OID mech,dh_token_t token,dh_key_set_t keys)114*7c478bd9Sstevel@tonic-gate __make_ap_token(gss_buffer_t result, /* The serialized token */
115*7c478bd9Sstevel@tonic-gate gss_OID mech, /* The mechanism this is for */
116*7c478bd9Sstevel@tonic-gate dh_token_t token, /* The unserialized input token */
117*7c478bd9Sstevel@tonic-gate dh_key_set_t keys /* The session keys to sign the token */)
118*7c478bd9Sstevel@tonic-gate {
119*7c478bd9Sstevel@tonic-gate unsigned int size, hsize, token_size, app_size, oid_size, start;
120*7c478bd9Sstevel@tonic-gate XDR xdrs;
121*7c478bd9Sstevel@tonic-gate unsigned char *sv, *buf, *xdrmem;
122*7c478bd9Sstevel@tonic-gate OM_uint32 stat;
123*7c478bd9Sstevel@tonic-gate
124*7c478bd9Sstevel@tonic-gate /* Allocate the signature for the input token */
125*7c478bd9Sstevel@tonic-gate if ((stat = __alloc_sig(get_qop(token),
126*7c478bd9Sstevel@tonic-gate &token->verifier))
127*7c478bd9Sstevel@tonic-gate != DH_SUCCESS)
128*7c478bd9Sstevel@tonic-gate return (stat);
129*7c478bd9Sstevel@tonic-gate
130*7c478bd9Sstevel@tonic-gate /*
131*7c478bd9Sstevel@tonic-gate * We will first determine the size of the output token in
132*7c478bd9Sstevel@tonic-gate * a bottom up fashion.
133*7c478bd9Sstevel@tonic-gate */
134*7c478bd9Sstevel@tonic-gate
135*7c478bd9Sstevel@tonic-gate /* Fetch the size of a serialized DH token */
136*7c478bd9Sstevel@tonic-gate token_size = xdr_sizeof((xdrproc_t)xdr_dh_token_desc, (void *)token);
137*7c478bd9Sstevel@tonic-gate
138*7c478bd9Sstevel@tonic-gate /*
139*7c478bd9Sstevel@tonic-gate * The token itself needs to be pasted on to the ASN.1
140*7c478bd9Sstevel@tonic-gate * application header on BYTES_PER_XDR_UNIT boundry. So we may
141*7c478bd9Sstevel@tonic-gate * need upto BYTES_PER_XDR_UNIT - 1 extra bytes.
142*7c478bd9Sstevel@tonic-gate */
143*7c478bd9Sstevel@tonic-gate token_size += BYTES_PER_XDR_UNIT -1;
144*7c478bd9Sstevel@tonic-gate
145*7c478bd9Sstevel@tonic-gate
146*7c478bd9Sstevel@tonic-gate oid_size = mech->length;
147*7c478bd9Sstevel@tonic-gate oid_size += der_length_size(mech->length);
148*7c478bd9Sstevel@tonic-gate oid_size += 1; /* tag x06 for Oid */
149*7c478bd9Sstevel@tonic-gate /* bytes to store the length */
150*7c478bd9Sstevel@tonic-gate app_size = der_length_size(oid_size + token_size);
151*7c478bd9Sstevel@tonic-gate
152*7c478bd9Sstevel@tonic-gate hsize = app_size + oid_size;
153*7c478bd9Sstevel@tonic-gate hsize += 1; /* tag 0x60 for application 0 */
154*7c478bd9Sstevel@tonic-gate size = hsize + token_size;
155*7c478bd9Sstevel@tonic-gate
156*7c478bd9Sstevel@tonic-gate /* Allocate a buffer to serialize into */
157*7c478bd9Sstevel@tonic-gate buf = New(unsigned char, size);
158*7c478bd9Sstevel@tonic-gate if (buf == NULL) {
159*7c478bd9Sstevel@tonic-gate __free_signature(&token->verifier);
160*7c478bd9Sstevel@tonic-gate return (DH_NOMEM_FAILURE);
161*7c478bd9Sstevel@tonic-gate }
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate result->value = sv = buf;
164*7c478bd9Sstevel@tonic-gate result->length = size;
165*7c478bd9Sstevel@tonic-gate
166*7c478bd9Sstevel@tonic-gate /* ASN.1 application 0 header */
167*7c478bd9Sstevel@tonic-gate
168*7c478bd9Sstevel@tonic-gate /* Encode the tag */
169*7c478bd9Sstevel@tonic-gate *buf++ = 0x60;
170*7c478bd9Sstevel@tonic-gate /* Encode the app length */
171*7c478bd9Sstevel@tonic-gate put_der_length(oid_size + token_size, &buf, app_size);
172*7c478bd9Sstevel@tonic-gate
173*7c478bd9Sstevel@tonic-gate /* Encode the OID tag */
174*7c478bd9Sstevel@tonic-gate *buf++ = 0x06;
175*7c478bd9Sstevel@tonic-gate /* Encode the OID length */
176*7c478bd9Sstevel@tonic-gate put_der_length(mech->length, &buf, oid_size);
177*7c478bd9Sstevel@tonic-gate /* Encode the OID elemeents */
178*7c478bd9Sstevel@tonic-gate memcpy(buf, mech->elements, mech->length);
179*7c478bd9Sstevel@tonic-gate
180*7c478bd9Sstevel@tonic-gate /* Encode the Diffie-Hellmam token */
181*7c478bd9Sstevel@tonic-gate /*
182*7c478bd9Sstevel@tonic-gate * Token has to be on BYTES_PER_XDR_UNIT boundry. (RNDUP is
183*7c478bd9Sstevel@tonic-gate * from xdr.h)
184*7c478bd9Sstevel@tonic-gate */
185*7c478bd9Sstevel@tonic-gate start = RNDUP(hsize);
186*7c478bd9Sstevel@tonic-gate /* Buffer for xdrmem_create to use */
187*7c478bd9Sstevel@tonic-gate xdrmem = &sv[start];
188*7c478bd9Sstevel@tonic-gate
189*7c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, (caddr_t)xdrmem, token_size, XDR_ENCODE);
190*7c478bd9Sstevel@tonic-gate /* Paste the DH token on */
191*7c478bd9Sstevel@tonic-gate if ((stat = __xdr_encode_token(&xdrs, NULL, token, keys))
192*7c478bd9Sstevel@tonic-gate != DH_SUCCESS) {
193*7c478bd9Sstevel@tonic-gate __free_signature(&token->verifier);
194*7c478bd9Sstevel@tonic-gate __dh_release_buffer(result);
195*7c478bd9Sstevel@tonic-gate }
196*7c478bd9Sstevel@tonic-gate
197*7c478bd9Sstevel@tonic-gate /* We're done with the signature, the token has been serialized */
198*7c478bd9Sstevel@tonic-gate __free_signature(&token->verifier);
199*7c478bd9Sstevel@tonic-gate
200*7c478bd9Sstevel@tonic-gate return (stat);
201*7c478bd9Sstevel@tonic-gate }
202*7c478bd9Sstevel@tonic-gate
203*7c478bd9Sstevel@tonic-gate /*
204*7c478bd9Sstevel@tonic-gate * __make_token: Given an unserialized DH token, serialize it puting the
205*7c478bd9Sstevel@tonic-gate * serialized output in result. If this token has a type of DH_MIC, then
206*7c478bd9Sstevel@tonic-gate * the optional message, msg, should be supplied. The mic caluclated will be
207*7c478bd9Sstevel@tonic-gate * over the message as well as the serialized token.
208*7c478bd9Sstevel@tonic-gate */
209*7c478bd9Sstevel@tonic-gate OM_uint32
__make_token(gss_buffer_t result,gss_buffer_t msg,dh_token_t token,dh_key_set_t keys)210*7c478bd9Sstevel@tonic-gate __make_token(gss_buffer_t result, /* Serialized token goes here */
211*7c478bd9Sstevel@tonic-gate gss_buffer_t msg, /* Optional message for DH_MIC tokens */
212*7c478bd9Sstevel@tonic-gate dh_token_t token, /* The token to encode */
213*7c478bd9Sstevel@tonic-gate dh_key_set_t keys /* The keys to encrypt the check sum with */)
214*7c478bd9Sstevel@tonic-gate {
215*7c478bd9Sstevel@tonic-gate unsigned int token_size;
216*7c478bd9Sstevel@tonic-gate XDR xdrs;
217*7c478bd9Sstevel@tonic-gate unsigned char *buf;
218*7c478bd9Sstevel@tonic-gate OM_uint32 stat;
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate /* Allocate a signature for this token */
221*7c478bd9Sstevel@tonic-gate if ((stat = __alloc_sig(get_qop(token),
222*7c478bd9Sstevel@tonic-gate &token->verifier))
223*7c478bd9Sstevel@tonic-gate != DH_SUCCESS)
224*7c478bd9Sstevel@tonic-gate return (stat);
225*7c478bd9Sstevel@tonic-gate
226*7c478bd9Sstevel@tonic-gate /* Get the output token size to know how much to allocate */
227*7c478bd9Sstevel@tonic-gate token_size = xdr_sizeof((xdrproc_t)xdr_dh_token_desc, (void *)token);
228*7c478bd9Sstevel@tonic-gate
229*7c478bd9Sstevel@tonic-gate /* Allocate the buffer to hold the serialized token */
230*7c478bd9Sstevel@tonic-gate buf = New(unsigned char, token_size);
231*7c478bd9Sstevel@tonic-gate if (buf == NULL) {
232*7c478bd9Sstevel@tonic-gate __free_signature(&token->verifier);
233*7c478bd9Sstevel@tonic-gate return (DH_NOMEM_FAILURE);
234*7c478bd9Sstevel@tonic-gate }
235*7c478bd9Sstevel@tonic-gate
236*7c478bd9Sstevel@tonic-gate /* Set the result */
237*7c478bd9Sstevel@tonic-gate result->length = token_size;
238*7c478bd9Sstevel@tonic-gate result->value = (void *)buf;
239*7c478bd9Sstevel@tonic-gate
240*7c478bd9Sstevel@tonic-gate /* Create the xdr stream using the allocated buffer */
241*7c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, (char *)buf, token_size, XDR_ENCODE);
242*7c478bd9Sstevel@tonic-gate
243*7c478bd9Sstevel@tonic-gate /* Encode the token */
244*7c478bd9Sstevel@tonic-gate if ((stat = __xdr_encode_token(&xdrs, msg, token, keys))
245*7c478bd9Sstevel@tonic-gate != DH_SUCCESS) {
246*7c478bd9Sstevel@tonic-gate __free_signature(&token->verifier);
247*7c478bd9Sstevel@tonic-gate __dh_release_buffer(result);
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate
250*7c478bd9Sstevel@tonic-gate /* Release the signature */
251*7c478bd9Sstevel@tonic-gate __free_signature(&token->verifier);
252*7c478bd9Sstevel@tonic-gate return (stat);
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate /*
256*7c478bd9Sstevel@tonic-gate * __get_ap_token: This routine deserializes a Diffie-Hellman serialized
257*7c478bd9Sstevel@tonic-gate * token which has an ASN.1 application 0 header prepended. The resulting
258*7c478bd9Sstevel@tonic-gate * unserialized token supplied should be of type DH_INIT_CNTX..
259*7c478bd9Sstevel@tonic-gate *
260*7c478bd9Sstevel@tonic-gate * The ASN.1 applicationtion prefix and token is encoded as follows:
261*7c478bd9Sstevel@tonic-gate *
262*7c478bd9Sstevel@tonic-gate * +------+
263*7c478bd9Sstevel@tonic-gate * | 0x60 | 1 TAG for APPLICATION 0
264*7c478bd9Sstevel@tonic-gate * +------+
265*7c478bd9Sstevel@tonic-gate * | |
266*7c478bd9Sstevel@tonic-gate * ~ ~ app_size DER encoded length of oid_size + token_size
267*7c478bd9Sstevel@tonic-gate * | |
268*7c478bd9Sstevel@tonic-gate * +------+
269*7c478bd9Sstevel@tonic-gate * | 0x06 | 1 TAG for OID
270*7c478bd9Sstevel@tonic-gate * +------+
271*7c478bd9Sstevel@tonic-gate * | | der_length_size
272*7c478bd9Sstevel@tonic-gate * ~ ~ (mech->length) DER encoded length of mech->length
273*7c478bd9Sstevel@tonic-gate * | |
274*7c478bd9Sstevel@tonic-gate * +------+
275*7c478bd9Sstevel@tonic-gate * | |
276*7c478bd9Sstevel@tonic-gate * ~ ~ mech->length OID elements (mech->elements)
277*7c478bd9Sstevel@tonic-gate * | |
278*7c478bd9Sstevel@tonic-gate * +------+
279*7c478bd9Sstevel@tonic-gate * | 0x00 | 0-3 XDR padding
280*7c478bd9Sstevel@tonic-gate * +------+
281*7c478bd9Sstevel@tonic-gate * | |
282*7c478bd9Sstevel@tonic-gate * ~ ~ Serialized DH token
283*7c478bd9Sstevel@tonic-gate * | |
284*7c478bd9Sstevel@tonic-gate * +------+
285*7c478bd9Sstevel@tonic-gate * | 0x00 | 0-3 Left over XDR padding
286*7c478bd9Sstevel@tonic-gate * +------+
287*7c478bd9Sstevel@tonic-gate *
288*7c478bd9Sstevel@tonic-gate * We will define the token_size to be the sizeof the serialize token plus
289*7c478bd9Sstevel@tonic-gate * 3 the maximum XDR paddinging that will be needed. Thus the XDR padding
290*7c478bd9Sstevel@tonic-gate * plus the left over XDR padding will alway equal 3.
291*7c478bd9Sstevel@tonic-gate */
292*7c478bd9Sstevel@tonic-gate OM_uint32
__get_ap_token(gss_buffer_t input,gss_OID mech,dh_token_t token,dh_signature_t sig)293*7c478bd9Sstevel@tonic-gate __get_ap_token(gss_buffer_t input, /* The token to deserialize */
294*7c478bd9Sstevel@tonic-gate gss_OID mech, /* This context's OID */
295*7c478bd9Sstevel@tonic-gate dh_token_t token, /* The resulting token */
296*7c478bd9Sstevel@tonic-gate dh_signature_t sig /* The signature found over the input token */)
297*7c478bd9Sstevel@tonic-gate {
298*7c478bd9Sstevel@tonic-gate unsigned char *buf, *p;
299*7c478bd9Sstevel@tonic-gate unsigned int oid_len, token_len, bytes, hsize;
300*7c478bd9Sstevel@tonic-gate int len;
301*7c478bd9Sstevel@tonic-gate OM_uint32 stat;
302*7c478bd9Sstevel@tonic-gate XDR xdrs;
303*7c478bd9Sstevel@tonic-gate
304*7c478bd9Sstevel@tonic-gate /* Set p and buf to point to the beginning of the token */
305*7c478bd9Sstevel@tonic-gate p = buf = (unsigned char *)input->value;
306*7c478bd9Sstevel@tonic-gate
307*7c478bd9Sstevel@tonic-gate /* Check that this is an ASN.1 APPLICATION 0 token */
308*7c478bd9Sstevel@tonic-gate if (*p++ != 0x60)
309*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gate /* Determine the length for the DER encoding of the packet length */
312*7c478bd9Sstevel@tonic-gate if ((len = get_der_length(&p, input->length - 1, &bytes)) < 0)
313*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
314*7c478bd9Sstevel@tonic-gate
315*7c478bd9Sstevel@tonic-gate /*
316*7c478bd9Sstevel@tonic-gate * See if the number of bytes specified by the
317*7c478bd9Sstevel@tonic-gate * encoded length is all there
318*7c478bd9Sstevel@tonic-gate */
319*7c478bd9Sstevel@tonic-gate if (input->length - 1 - bytes != len)
320*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate /*
323*7c478bd9Sstevel@tonic-gate * Running total of the APPLICATION 0 prefix so far. One for the
324*7c478bd9Sstevel@tonic-gate * tag (0x60) and the bytes necessary to encode the length of the
325*7c478bd9Sstevel@tonic-gate * packet.
326*7c478bd9Sstevel@tonic-gate */
327*7c478bd9Sstevel@tonic-gate hsize = 1 + bytes;
328*7c478bd9Sstevel@tonic-gate
329*7c478bd9Sstevel@tonic-gate /* Check that we're now looking at an OID */
330*7c478bd9Sstevel@tonic-gate if (*p++ != 0x06)
331*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
332*7c478bd9Sstevel@tonic-gate
333*7c478bd9Sstevel@tonic-gate /* Get OID length and the number of bytes that to encode it */
334*7c478bd9Sstevel@tonic-gate oid_len = get_der_length(&p, len - 1, &bytes);
335*7c478bd9Sstevel@tonic-gate
336*7c478bd9Sstevel@tonic-gate /*
337*7c478bd9Sstevel@tonic-gate * Now add the byte for the OID tag, plus the bytes for the oid
338*7c478bd9Sstevel@tonic-gate * length, plus the oid length its self. That is, add the size
339*7c478bd9Sstevel@tonic-gate * of the encoding of the OID to the running total of the
340*7c478bd9Sstevel@tonic-gate * APPLICATION 0 header. The result is the total size of the header.
341*7c478bd9Sstevel@tonic-gate */
342*7c478bd9Sstevel@tonic-gate hsize += 1 + bytes + oid_len;
343*7c478bd9Sstevel@tonic-gate
344*7c478bd9Sstevel@tonic-gate /*
345*7c478bd9Sstevel@tonic-gate * The DH token length is the application length minus the length
346*7c478bd9Sstevel@tonic-gate * of the OID encoding.
347*7c478bd9Sstevel@tonic-gate */
348*7c478bd9Sstevel@tonic-gate token_len = len - 1 - bytes - oid_len;
349*7c478bd9Sstevel@tonic-gate
350*7c478bd9Sstevel@tonic-gate /* Sanity check the token length */
351*7c478bd9Sstevel@tonic-gate if (input->length - hsize != token_len)
352*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
353*7c478bd9Sstevel@tonic-gate
354*7c478bd9Sstevel@tonic-gate /* Check that this token is for this OID */
355*7c478bd9Sstevel@tonic-gate if (mech->length != oid_len)
356*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
357*7c478bd9Sstevel@tonic-gate if (memcmp(mech->elements, p, oid_len) != 0)
358*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
359*7c478bd9Sstevel@tonic-gate
360*7c478bd9Sstevel@tonic-gate /* Round up the header size to XDR boundry */
361*7c478bd9Sstevel@tonic-gate hsize = RNDUP(hsize);
362*7c478bd9Sstevel@tonic-gate
363*7c478bd9Sstevel@tonic-gate /* Get the start of XDR encoded token */
364*7c478bd9Sstevel@tonic-gate p = &buf[hsize];
365*7c478bd9Sstevel@tonic-gate
366*7c478bd9Sstevel@tonic-gate /* Create and XDR stream to decode from */
367*7c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, (caddr_t)p, token_len, XDR_DECODE);
368*7c478bd9Sstevel@tonic-gate
369*7c478bd9Sstevel@tonic-gate /*
370*7c478bd9Sstevel@tonic-gate * Clear the deserialized token (we'll have the xdr routines
371*7c478bd9Sstevel@tonic-gate * do the the allocations).
372*7c478bd9Sstevel@tonic-gate */
373*7c478bd9Sstevel@tonic-gate memset(token, 0, sizeof (dh_token_desc));
374*7c478bd9Sstevel@tonic-gate
375*7c478bd9Sstevel@tonic-gate /* Zero out the signature */
376*7c478bd9Sstevel@tonic-gate memset(sig, 0, sizeof (*sig));
377*7c478bd9Sstevel@tonic-gate
378*7c478bd9Sstevel@tonic-gate /*
379*7c478bd9Sstevel@tonic-gate * Decode the DH_INIT_CNTX token. Note that at this point we have no
380*7c478bd9Sstevel@tonic-gate * session keys established, so that keys is null. The unencrypted
381*7c478bd9Sstevel@tonic-gate * signature will be made available to the caller in sig. The
382*7c478bd9Sstevel@tonic-gate * caller can then attempt to decrypt the session keys in token
383*7c478bd9Sstevel@tonic-gate * and encrypt the returned sig with those keys to check the
384*7c478bd9Sstevel@tonic-gate * integrity of the token.
385*7c478bd9Sstevel@tonic-gate */
386*7c478bd9Sstevel@tonic-gate if ((stat = __xdr_decode_token(&xdrs, NULL, token, NULL, sig))
387*7c478bd9Sstevel@tonic-gate != DH_SUCCESS) {
388*7c478bd9Sstevel@tonic-gate xdr_free(xdr_dh_token_desc, (char *)token);
389*7c478bd9Sstevel@tonic-gate return (stat);
390*7c478bd9Sstevel@tonic-gate }
391*7c478bd9Sstevel@tonic-gate
392*7c478bd9Sstevel@tonic-gate return (stat);
393*7c478bd9Sstevel@tonic-gate }
394*7c478bd9Sstevel@tonic-gate
395*7c478bd9Sstevel@tonic-gate /*
396*7c478bd9Sstevel@tonic-gate * __get_token: Deserialize a supplied Diffie-Hellman token. Note the
397*7c478bd9Sstevel@tonic-gate * session keys should always be supplied to this routine. The message
398*7c478bd9Sstevel@tonic-gate * should only be supplied if the token is of DH_MIC type.
399*7c478bd9Sstevel@tonic-gate */
400*7c478bd9Sstevel@tonic-gate OM_uint32
__get_token(gss_buffer_t input,gss_buffer_t msg,dh_token_t token,dh_key_set_t keys)401*7c478bd9Sstevel@tonic-gate __get_token(gss_buffer_t input, /* The token to deserialize */
402*7c478bd9Sstevel@tonic-gate gss_buffer_t msg, /* Optional message to generate verifier over */
403*7c478bd9Sstevel@tonic-gate dh_token_t token, /* The decode token */
404*7c478bd9Sstevel@tonic-gate dh_key_set_t keys /* The session keys */)
405*7c478bd9Sstevel@tonic-gate {
406*7c478bd9Sstevel@tonic-gate XDR xdrs;
407*7c478bd9Sstevel@tonic-gate dh_signature sig;
408*7c478bd9Sstevel@tonic-gate OM_uint32 stat;
409*7c478bd9Sstevel@tonic-gate
410*7c478bd9Sstevel@tonic-gate /* Create a an XDR stream out of the input token */
411*7c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, (caddr_t)input->value, input->length, XDR_DECODE);
412*7c478bd9Sstevel@tonic-gate
413*7c478bd9Sstevel@tonic-gate /* Clear the token_desc and signature. */
414*7c478bd9Sstevel@tonic-gate memset(token, 0, sizeof (dh_token_desc));
415*7c478bd9Sstevel@tonic-gate memset(&sig, 0, sizeof (sig));
416*7c478bd9Sstevel@tonic-gate
417*7c478bd9Sstevel@tonic-gate /* Decode the token */
418*7c478bd9Sstevel@tonic-gate if ((stat = __xdr_decode_token(&xdrs, msg, token, keys, &sig))
419*7c478bd9Sstevel@tonic-gate != DH_SUCCESS)
420*7c478bd9Sstevel@tonic-gate /* If we fail release the deserialized token */
421*7c478bd9Sstevel@tonic-gate xdr_free(xdr_dh_token_desc, (char *)token);
422*7c478bd9Sstevel@tonic-gate
423*7c478bd9Sstevel@tonic-gate /* We always free the signature */
424*7c478bd9Sstevel@tonic-gate __free_signature(&sig);
425*7c478bd9Sstevel@tonic-gate
426*7c478bd9Sstevel@tonic-gate return (stat);
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate
429*7c478bd9Sstevel@tonic-gate /*
430*7c478bd9Sstevel@tonic-gate * Warning these routines assumes that xdrs was created with xdrmem_create!
431*7c478bd9Sstevel@tonic-gate */
432*7c478bd9Sstevel@tonic-gate
433*7c478bd9Sstevel@tonic-gate /*
434*7c478bd9Sstevel@tonic-gate * __xdr_encode_token: Given an allocated xdrs stream serialize the supplied
435*7c478bd9Sstevel@tonic-gate * token_desc pointed to by objp, using keys to encrypt the signature. If
436*7c478bd9Sstevel@tonic-gate * msg is non null then calculate the signature over msg as well as the
437*7c478bd9Sstevel@tonic-gate * serialized token. Note this protocol is designed with the signature as
438*7c478bd9Sstevel@tonic-gate * the last part of any token. In this way the signature that is calculated is
439*7c478bd9Sstevel@tonic-gate * always done over the entire token. All fields in any token are thus
440*7c478bd9Sstevel@tonic-gate * protected from tampering
441*7c478bd9Sstevel@tonic-gate */
442*7c478bd9Sstevel@tonic-gate static OM_uint32
__xdr_encode_token(register XDR * xdrs,gss_buffer_t msg,dh_token_desc * objp,dh_key_set_t keys)443*7c478bd9Sstevel@tonic-gate __xdr_encode_token(register XDR *xdrs, gss_buffer_t msg,
444*7c478bd9Sstevel@tonic-gate dh_token_desc *objp, dh_key_set_t keys)
445*7c478bd9Sstevel@tonic-gate {
446*7c478bd9Sstevel@tonic-gate OM_uint32 stat;
447*7c478bd9Sstevel@tonic-gate
448*7c478bd9Sstevel@tonic-gate /* Check that xdrs is valid */
449*7c478bd9Sstevel@tonic-gate if (xdrs == 0 || xdrs->x_op != XDR_ENCODE)
450*7c478bd9Sstevel@tonic-gate return (DH_BADARG_FAILURE);
451*7c478bd9Sstevel@tonic-gate
452*7c478bd9Sstevel@tonic-gate /* Encode the protocol versioned body */
453*7c478bd9Sstevel@tonic-gate if (!xdr_dh_version(xdrs, &objp->ver))
454*7c478bd9Sstevel@tonic-gate return (DH_ENCODE_FAILURE);
455*7c478bd9Sstevel@tonic-gate
456*7c478bd9Sstevel@tonic-gate /* Calculate the signature */
457*7c478bd9Sstevel@tonic-gate stat = __mk_sig(get_qop(objp), xdrs->x_base,
458*7c478bd9Sstevel@tonic-gate xdr_getpos(xdrs), msg, keys,
459*7c478bd9Sstevel@tonic-gate &objp->verifier);
460*7c478bd9Sstevel@tonic-gate
461*7c478bd9Sstevel@tonic-gate if (stat != DH_SUCCESS)
462*7c478bd9Sstevel@tonic-gate return (stat);
463*7c478bd9Sstevel@tonic-gate
464*7c478bd9Sstevel@tonic-gate /* Encode the signature */
465*7c478bd9Sstevel@tonic-gate if (!xdr_dh_signature(xdrs, &objp->verifier))
466*7c478bd9Sstevel@tonic-gate return (DH_ENCODE_FAILURE);
467*7c478bd9Sstevel@tonic-gate
468*7c478bd9Sstevel@tonic-gate return (DH_SUCCESS);
469*7c478bd9Sstevel@tonic-gate }
470*7c478bd9Sstevel@tonic-gate
471*7c478bd9Sstevel@tonic-gate /*
472*7c478bd9Sstevel@tonic-gate * __xdr_decode_token: Decode a token from an XDR stream into a token_desc
473*7c478bd9Sstevel@tonic-gate * pointed to by objp. We will calculate a signature over the serialized
474*7c478bd9Sstevel@tonic-gate * token and an optional message. The calculated signature will be
475*7c478bd9Sstevel@tonic-gate * returned to the caller in sig. If the supplied keys are available this
476*7c478bd9Sstevel@tonic-gate * routine will compare that the verifier in the deserialized token is
477*7c478bd9Sstevel@tonic-gate * the same as the calculated signature over the input stream. This is
478*7c478bd9Sstevel@tonic-gate * the usual case. However if the supplied serialized token is DH_INIT_CNTX,
479*7c478bd9Sstevel@tonic-gate * the keys have not yet been established. So we just give the caller back
480*7c478bd9Sstevel@tonic-gate * our raw signature (Non encrypted) and the deserialized token. Higher in
481*7c478bd9Sstevel@tonic-gate * the food chain (currently __dh_gss_accept_sec_context), we will attempt
482*7c478bd9Sstevel@tonic-gate * to decrypt the session keys and call __verify_sig with the decrypted
483*7c478bd9Sstevel@tonic-gate * session keys the signature returned from this routine and the deserialized
484*7c478bd9Sstevel@tonic-gate * token.
485*7c478bd9Sstevel@tonic-gate *
486*7c478bd9Sstevel@tonic-gate * Note it is assumed that sig does point to a valid uninitialized signature.
487*7c478bd9Sstevel@tonic-gate */
488*7c478bd9Sstevel@tonic-gate
489*7c478bd9Sstevel@tonic-gate static OM_uint32
__xdr_decode_token(register XDR * xdrs,gss_buffer_t msg,dh_token_desc * objp,dh_key_set_t keys,dh_signature_t sig)490*7c478bd9Sstevel@tonic-gate __xdr_decode_token(register XDR *xdrs, gss_buffer_t msg,
491*7c478bd9Sstevel@tonic-gate dh_token_desc *objp, dh_key_set_t keys, dh_signature_t sig)
492*7c478bd9Sstevel@tonic-gate {
493*7c478bd9Sstevel@tonic-gate OM_uint32 stat;
494*7c478bd9Sstevel@tonic-gate
495*7c478bd9Sstevel@tonic-gate /* Check that we are decoding */
496*7c478bd9Sstevel@tonic-gate if (xdrs == 0 || xdrs->x_op != XDR_DECODE)
497*7c478bd9Sstevel@tonic-gate return (DH_BADARG_FAILURE);
498*7c478bd9Sstevel@tonic-gate
499*7c478bd9Sstevel@tonic-gate /* Decode the protocol versioned body */
500*7c478bd9Sstevel@tonic-gate if (!xdr_dh_version(xdrs, &objp->ver))
501*7c478bd9Sstevel@tonic-gate return (DH_DECODE_FAILURE);
502*7c478bd9Sstevel@tonic-gate
503*7c478bd9Sstevel@tonic-gate /* Allocate the signature for this tokens QOP */
504*7c478bd9Sstevel@tonic-gate if ((stat = __alloc_sig(get_qop(objp), sig)) != DH_SUCCESS)
505*7c478bd9Sstevel@tonic-gate return (stat);
506*7c478bd9Sstevel@tonic-gate
507*7c478bd9Sstevel@tonic-gate /*
508*7c478bd9Sstevel@tonic-gate * Call __mk_sig in crypto.c to calculate the signature based on
509*7c478bd9Sstevel@tonic-gate * the decoded QOP. __mk_sig will encrypt the signature with the
510*7c478bd9Sstevel@tonic-gate * supplied keys if they are available. If keys is null the signature
511*7c478bd9Sstevel@tonic-gate * will be just the unencrypted check sum.
512*7c478bd9Sstevel@tonic-gate */
513*7c478bd9Sstevel@tonic-gate stat = __mk_sig(get_qop(objp), xdrs->x_base,
514*7c478bd9Sstevel@tonic-gate xdr_getpos(xdrs), msg, keys, sig);
515*7c478bd9Sstevel@tonic-gate if (stat != DH_SUCCESS)
516*7c478bd9Sstevel@tonic-gate return (stat);
517*7c478bd9Sstevel@tonic-gate
518*7c478bd9Sstevel@tonic-gate /* Now decode the supplied signature */
519*7c478bd9Sstevel@tonic-gate if (!xdr_dh_signature(xdrs, &objp->verifier))
520*7c478bd9Sstevel@tonic-gate return (stat);
521*7c478bd9Sstevel@tonic-gate
522*7c478bd9Sstevel@tonic-gate /*
523*7c478bd9Sstevel@tonic-gate * If we have keys then we can check that the signatures
524*7c478bd9Sstevel@tonic-gate * are the same
525*7c478bd9Sstevel@tonic-gate */
526*7c478bd9Sstevel@tonic-gate if (keys && !__cmpsig(sig, &objp->verifier))
527*7c478bd9Sstevel@tonic-gate return (DH_VERIFIER_MISMATCH);
528*7c478bd9Sstevel@tonic-gate
529*7c478bd9Sstevel@tonic-gate return (DH_SUCCESS);
530*7c478bd9Sstevel@tonic-gate }
531