1178828Sdfr/*-
2178828Sdfr * Copyright (c) 2008 Doug Rabson
3178828Sdfr * All rights reserved.
4178828Sdfr *
5178828Sdfr * Redistribution and use in source and binary forms, with or without
6178828Sdfr * modification, are permitted provided that the following conditions
7178828Sdfr * are met:
8178828Sdfr * 1. Redistributions of source code must retain the above copyright
9178828Sdfr *    notice, this list of conditions and the following disclaimer.
10178828Sdfr * 2. Redistributions in binary form must reproduce the above copyright
11178828Sdfr *    notice, this list of conditions and the following disclaimer in the
12178828Sdfr *    documentation and/or other materials provided with the distribution.
13178828Sdfr *
14178828Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15178828Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16178828Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17178828Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18178828Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19178828Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20178828Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21178828Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22178828Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23178828Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24178828Sdfr * SUCH DAMAGE.
25178828Sdfr *
26178828Sdfr * $FreeBSD$
27178828Sdfr */
28178828Sdfr
29178828Sdfr#include <gssapi/gssapi.h>
30178828Sdfr#include <stdlib.h>
31178828Sdfr#include <string.h>
32178828Sdfr
33178828Sdfr#include "utils.h"
34178828Sdfr
35178828SdfrOM_uint32
36178828Sdfrgss_encapsulate_token(const gss_buffer_t input_token, gss_OID oid,
37178828Sdfr    gss_buffer_t output_token)
38178828Sdfr{
39178828Sdfr	unsigned char *p;
40178828Sdfr	size_t len, inside_len;
41178828Sdfr	size_t a, b;
42178828Sdfr	int i;
43178828Sdfr
44178828Sdfr	_gss_buffer_zero(output_token);
45178828Sdfr
46178828Sdfr	/*
47178828Sdfr	 * First time around, we calculate the size, second time, we
48178828Sdfr	 * encode the token.
49178828Sdfr	 */
50178828Sdfr	p = 0;
51178828Sdfr	for (i = 0; i < 2; i++) {
52178828Sdfr		len = 0;
53178828Sdfr
54178828Sdfr		/*
55178828Sdfr		 * Token starts with [APPLICATION 0] SEQUENCE.
56178828Sdfr		 */
57178828Sdfr		if (p)
58178828Sdfr			*p++ = 0x60;
59178828Sdfr		len++;
60178828Sdfr
61178828Sdfr		/*
62178828Sdfr		 * The length embedded in the token is the space
63178828Sdfr		 * needed for the encapsulated oid plus the length of
64178828Sdfr		 * the inner token.
65178828Sdfr		 */
66178828Sdfr		if (oid->length > 127)
67178828Sdfr			return (GSS_S_DEFECTIVE_TOKEN);
68178828Sdfr
69178828Sdfr		inside_len = 2 + oid->length + input_token->length;
70178828Sdfr
71178828Sdfr		/*
72178828Sdfr		 * Figure out how to encode the length
73178828Sdfr		 */
74178828Sdfr		if (inside_len < 128) {
75178828Sdfr			if (p)
76178828Sdfr				*p++ = inside_len;
77178828Sdfr			len++;
78178828Sdfr		} else {
79178828Sdfr			b = 1;
80178828Sdfr			if (inside_len >= 0x100)
81178828Sdfr				b++;
82178828Sdfr			if (inside_len >= 0x10000)
83178828Sdfr				b++;
84178828Sdfr			if (inside_len >= 0x1000000)
85178828Sdfr				b++;
86178828Sdfr			if (p)
87178828Sdfr				*p++ = b | 0x80;
88178828Sdfr			len++;
89178828Sdfr			a = inside_len << 8*(4 - b);
90178828Sdfr			while (b) {
91178828Sdfr				if (p)
92178828Sdfr					*p++ = (a >> 24);
93178828Sdfr				a <<= 8;
94178828Sdfr				len++;
95178828Sdfr				b--;
96178828Sdfr			}
97178828Sdfr		}
98178828Sdfr
99178828Sdfr		/*
100178828Sdfr		 * Encode the OID for the mechanism. Simplify life by
101178828Sdfr		 * assuming that the OID length is less than 128 bytes.
102178828Sdfr		 */
103178828Sdfr		if (p)
104178828Sdfr			*p++ = 0x06;
105178828Sdfr		len++;
106178828Sdfr		if (p)
107178828Sdfr			*p++ = oid->length;
108178828Sdfr		len++;
109178828Sdfr		if (p) {
110178828Sdfr			memcpy(p, oid->elements, oid->length);
111178828Sdfr			p += oid->length;
112178828Sdfr		}
113178828Sdfr		len += oid->length;
114178828Sdfr
115178828Sdfr		if (p) {
116178828Sdfr			memcpy(p, input_token->value, input_token->length);
117178828Sdfr			p += input_token->length;
118178828Sdfr		}
119178828Sdfr		len += input_token->length;
120178828Sdfr
121178828Sdfr		if (i == 0) {
122178828Sdfr			output_token->length = len;
123178828Sdfr			output_token->value = malloc(len);
124178828Sdfr			if (!output_token->value)
125178828Sdfr				return (GSS_S_DEFECTIVE_TOKEN);
126178828Sdfr			p = output_token->value;
127178828Sdfr		}
128178828Sdfr	}
129178828Sdfr
130178828Sdfr	return (GSS_S_COMPLETE);
131178828Sdfr}
132