1251876Speter/*	$NetBSD: mk_safe.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2251876Speter
3251876Speter/*
4251876Speter * Copyright (c) 1997 - 2003 Kungliga Tekniska H��gskolan
5251876Speter * (Royal Institute of Technology, Stockholm, Sweden).
6251876Speter * All rights reserved.
7251876Speter *
8251876Speter * Redistribution and use in source and binary forms, with or without
9251876Speter * modification, are permitted provided that the following conditions
10251876Speter * are met:
11251876Speter *
12251876Speter * 1. Redistributions of source code must retain the above copyright
13251876Speter *    notice, this list of conditions and the following disclaimer.
14251876Speter *
15251876Speter * 2. Redistributions in binary form must reproduce the above copyright
16251876Speter *    notice, this list of conditions and the following disclaimer in the
17251876Speter *    documentation and/or other materials provided with the distribution.
18251876Speter *
19251876Speter * 3. Neither the name of the Institute nor the names of its contributors
20251876Speter *    may be used to endorse or promote products derived from this software
21251876Speter *    without specific prior written permission.
22251876Speter *
23251876Speter * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24251876Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25251876Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26251876Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27251876Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28251876Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29251876Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30251876Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31251876Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32251876Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33251876Speter * SUCH DAMAGE.
34251876Speter */
35251876Speter
36251876Speter#include "krb5_locl.h"
37251876Speter
38251876SpeterKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
39251876Speterkrb5_mk_safe(krb5_context context,
40251876Speter	     krb5_auth_context auth_context,
41251876Speter	     const krb5_data *userdata,
42251876Speter	     krb5_data *outbuf,
43251876Speter	     krb5_replay_data *outdata)
44251876Speter{
45251876Speter    krb5_error_code ret;
46251876Speter    KRB_SAFE s;
47251876Speter    u_char *buf = NULL;
48251876Speter    size_t buf_size;
49251876Speter    size_t len = 0;
50251876Speter    krb5_crypto crypto;
51251876Speter    krb5_keyblock *key;
52251876Speter    krb5_replay_data rdata;
53251876Speter
54251876Speter    if ((auth_context->flags &
55251876Speter	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
56251876Speter	outdata == NULL)
57251876Speter	return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
58251876Speter
59251876Speter    if (auth_context->local_subkey)
60251876Speter	key = auth_context->local_subkey;
61251876Speter    else if (auth_context->remote_subkey)
62251876Speter	key = auth_context->remote_subkey;
63251876Speter    else
64251876Speter	key = auth_context->keyblock;
65251876Speter
66251876Speter    s.pvno = 5;
67251876Speter    s.msg_type = krb_safe;
68251876Speter
69251876Speter    memset(&rdata, 0, sizeof(rdata));
70251876Speter
71251876Speter    s.safe_body.user_data = *userdata;
72251876Speter
73251876Speter    krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec);
74251876Speter
75251876Speter    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
76251876Speter	s.safe_body.timestamp  = &rdata.timestamp;
77251876Speter	s.safe_body.usec       = &rdata.usec;
78251876Speter    } else {
79251876Speter	s.safe_body.timestamp  = NULL;
80251876Speter	s.safe_body.usec       = NULL;
81251876Speter    }
82251876Speter
83251876Speter    if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) {
84251876Speter	outdata->timestamp = rdata.timestamp;
85251876Speter	outdata->usec = rdata.usec;
86251876Speter    }
87251876Speter
88251876Speter    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
89251876Speter	rdata.seq = auth_context->local_seqnumber;
90251876Speter	s.safe_body.seq_number = &rdata.seq;
91251876Speter    } else
92251876Speter	s.safe_body.seq_number = NULL;
93251876Speter
94251876Speter    if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
95251876Speter	outdata->seq = auth_context->local_seqnumber;
96251876Speter
97251876Speter    s.safe_body.s_address = auth_context->local_address;
98251876Speter    s.safe_body.r_address = auth_context->remote_address;
99251876Speter
100251876Speter    s.cksum.cksumtype       = 0;
101251876Speter    s.cksum.checksum.data   = NULL;
102251876Speter    s.cksum.checksum.length = 0;
103251876Speter
104251876Speter    ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, &s, &len, ret);
105251876Speter    if (ret)
106251876Speter	return ret;
107251876Speter    if(buf_size != len)
108251876Speter	krb5_abortx(context, "internal error in ASN.1 encoder");
109251876Speter    ret = krb5_crypto_init(context, key, 0, &crypto);
110251876Speter    if (ret) {
111251876Speter	free (buf);
112251876Speter	return ret;
113251876Speter    }
114251876Speter    ret = krb5_create_checksum(context,
115251876Speter			       crypto,
116251876Speter			       KRB5_KU_KRB_SAFE_CKSUM,
117251876Speter			       0,
118251876Speter			       buf,
119251876Speter			       len,
120251876Speter			       &s.cksum);
121251876Speter    krb5_crypto_destroy(context, crypto);
122251876Speter    if (ret) {
123251876Speter	free (buf);
124251876Speter	return ret;
125251876Speter    }
126251876Speter
127251876Speter    free(buf);
128251876Speter    ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, &s, &len, ret);
129251876Speter    free_Checksum (&s.cksum);
130251876Speter    if(ret)
131251876Speter	return ret;
132251876Speter    if(buf_size != len)
133251876Speter	krb5_abortx(context, "internal error in ASN.1 encoder");
134251876Speter
135251876Speter    outbuf->length = len;
136251876Speter    outbuf->data   = buf;
137251876Speter    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
138251876Speter	auth_context->local_seqnumber =
139251876Speter	    (auth_context->local_seqnumber + 1) & 0xFFFFFFFF;
140251876Speter    return 0;
141251876Speter}
142251876Speter