2 * lib/krb5/krb/mk_priv.c
4 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. M.I.T. makes no representations about the suitability of
20 * this software for any purpose. It is provided "as is" without express
21 * or implied warranty.
30 static krb5_error_code
31 krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr,
32 remote_addr, i_vector, outbuf)
34 const krb5_data * userdata;
35 const krb5_keyblock * keyblock;
36 krb5_replay_data * replaydata;
37 krb5_address * local_addr;
38 krb5_address * remote_addr;
39 krb5_pointer i_vector;
42 krb5_error_code retval;
43 krb5_encrypt_block eblock;
45 krb5_priv_enc_part privmsg_enc_part;
46 krb5_data *scratch1, *scratch2;
48 if (!valid_etype(keyblock->etype))
49 return KRB5_PROG_ETYPE_NOSUPP;
51 privmsg.enc_part.kvno = 0; /* XXX allow user-set? */
52 privmsg.enc_part.etype = keyblock->etype;
54 privmsg_enc_part.user_data = *userdata;
55 privmsg_enc_part.s_address = local_addr;
56 privmsg_enc_part.r_address = remote_addr;
58 /* We should check too make sure one exists. */
59 privmsg_enc_part.timestamp = replaydata->timestamp;
60 privmsg_enc_part.usec = replaydata->usec;
61 privmsg_enc_part.seq_number = replaydata->seq;
63 /* start by encoding to-be-encrypted part of the message */
64 if (retval = encode_krb5_enc_priv_part(&privmsg_enc_part, &scratch1))
67 /* put together an eblock for this encryption */
68 krb5_use_cstype(context, &eblock, keyblock->etype);
69 privmsg.enc_part.ciphertext.length = krb5_encrypt_size(scratch1->length,
71 /* add padding area, and zero it */
72 if (!(scratch1->data = realloc(scratch1->data,
73 privmsg.enc_part.ciphertext.length))) {
74 /* may destroy scratch1->data */
79 memset(scratch1->data + scratch1->length, 0,
80 privmsg.enc_part.ciphertext.length - scratch1->length);
81 if (!(privmsg.enc_part.ciphertext.data =
82 malloc(privmsg.enc_part.ciphertext.length))) {
87 /* do any necessary key pre-processing */
88 if (retval = krb5_process_key(context, &eblock, keyblock))
91 /* call the encryption routine */
92 if (retval = krb5_encrypt(context, (krb5_pointer) scratch1->data,
93 (krb5_pointer) privmsg.enc_part.ciphertext.data,
94 scratch1->length, &eblock,
96 krb5_finish_key(context, &eblock);
100 /* put last block into the i_vector */
103 privmsg.enc_part.ciphertext.data +
104 (privmsg.enc_part.ciphertext.length -
105 eblock.crypto_entry->block_length),
106 eblock.crypto_entry->block_length);
108 if (retval = encode_krb5_priv(&privmsg, &scratch2)) {
109 krb5_finish_key(context, &eblock);
113 /* encode private message */
114 if (retval = krb5_finish_key(context, &eblock))
118 krb5_xfree(scratch2);
122 memset(privmsg.enc_part.ciphertext.data, 0,
123 privmsg.enc_part.ciphertext.length);
124 free(privmsg.enc_part.ciphertext.data);
125 privmsg.enc_part.ciphertext.length = 0;
126 privmsg.enc_part.ciphertext.data = 0;
129 memset(scratch1->data, 0, scratch1->length);
130 krb5_free_data(context, scratch1);
137 krb5_mk_priv(context, auth_context, userdata, outbuf, outdata)
138 krb5_context context;
139 krb5_auth_context * auth_context;
140 const krb5_data * userdata;
142 krb5_replay_data * outdata;
144 krb5_replay_data replaydata;
145 krb5_error_code retval;
147 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
148 (auth_context->rcache == NULL))
149 return KRB5_RC_REQUIRED;
151 if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
152 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
154 /* Need a better error */
155 return KRB5_RC_REQUIRED;
157 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
158 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
159 if (retval = krb5_us_timeofday(context, &replaydata.timestamp,
162 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
163 outdata->timestamp = replaydata.timestamp;
164 outdata->usec = replaydata.usec;
167 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
168 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
169 replaydata.seq = auth_context->local_seq_number;
170 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
171 auth_context->local_seq_number++;
173 outdata->seq = replaydata.seq;
177 if (retval = krb5_mk_priv_basic(context, userdata, auth_context->keyblock,
178 &replaydata, auth_context->local_addr, auth_context->remote_addr,
179 auth_context->i_vector, outbuf))
182 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
183 krb5_donot_replay replay;
185 if (retval = krb5_gen_replay_name(context, auth_context->local_addr,
186 "_priv", &replay.client)) {
191 replay.server = ""; /* XXX */
192 replay.cusec = replaydata.usec;
193 replay.ctime = replaydata.timestamp;
194 if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) {
195 /* should we really error out here? XXX */
199 krb5_xfree(replay.client);
205 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
206 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
207 auth_context->local_seq_number--;