5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
25 /******************************************************************************
27 Authentication Payload
29 ******************************************************************************/
31 /* Authentication Payload structure */
32 struct SilcAuthPayloadStruct {
34 unsigned short auth_method;
35 unsigned short random_len;
36 unsigned char *random_data;
37 unsigned short auth_len;
38 unsigned char *auth_data;
41 /* Parses and returns Authentication Payload */
43 SilcAuthPayload silc_auth_payload_parse(SilcBuffer buffer)
48 SILC_LOG_DEBUG(("Parsing Authentication Payload"));
50 new = silc_calloc(1, sizeof(*new));
52 /* Parse the payload */
53 ret = silc_buffer_unformat(buffer,
54 SILC_STR_UI_SHORT(&new->len),
55 SILC_STR_UI_CHAR(&new->auth_method),
56 SILC_STR_UI16_NSTRING_ALLOC(&new->random_data,
58 SILC_STR_UI16_NSTRING_ALLOC(&new->auth_data,
66 if (new->len != buffer->len) {
67 silc_auth_payload_free(new);
71 /* If password authentication, random data must not be set */
72 if (new->auth_method == SILC_AUTH_PASSWORD && new->random_len) {
73 silc_auth_payload_free(new);
80 /* Encodes authentication payload into buffer and returns it */
82 SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
83 unsigned char *random_data,
84 unsigned short random_len,
85 unsigned char *auth_data,
86 unsigned short auth_len)
91 SILC_LOG_DEBUG(("Encoding Authentication Payload"));
93 len = 4 + 4 + random_len + auth_len;
94 buffer = silc_buffer_alloc(len);
95 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
96 silc_buffer_format(buffer,
97 SILC_STR_UI_SHORT(len),
98 SILC_STR_UI_SHORT(method),
99 SILC_STR_UI_SHORT(random_len),
100 SILC_STR_UI_XNSTRING(random_data, random_len),
101 SILC_STR_UI_SHORT(auth_len),
102 SILC_STR_UI_XNSTRING(auth_data, auth_len),
108 /* Frees authentication payload. */
110 void silc_auth_payload_free(SilcAuthPayload payload)
113 if (payload->random_data) {
114 memset(payload->random_data, 0, payload->random_len);
115 silc_free(payload->random_data);
117 if (payload->auth_data) {
118 memset(payload->auth_data, 0, payload->auth_len);
119 silc_free(payload->auth_data);
125 /******************************************************************************
127 Authentication Routines
129 ******************************************************************************/
131 /* Encodes the authentication data for hashing and signing as the protocol
134 static unsigned char *
135 silc_auth_public_key_encode_data(SilcPKCS pkcs, unsigned char *random,
136 unsigned int random_len, void *id,
137 SilcIdType type, unsigned int *ret_len)
140 unsigned char *pk, *id_data, *ret;
141 unsigned int pk_len, id_len;
143 pk = silc_pkcs_get_public_key(pkcs, &pk_len);
147 id_data = silc_id_id2str(id, type);
152 id_len = silc_id_get_len(type);
154 buf = silc_buffer_alloc(random_len + pk_len);
155 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
156 silc_buffer_format(buf,
157 SILC_STR_UI_XNSTRING(random, random_len),
158 SILC_STR_UI_XNSTRING(id_data, id_len),
159 SILC_STR_UI_XNSTRING(pk, pk_len),
162 ret = silc_calloc(buf->len, sizeof(*ret));
163 memcpy(ret, buf->data, buf->len);
168 silc_buffer_free(buf);
175 /* Generates Authentication Payload with authentication data. This is used
176 to do public key based authentication. This generates the random data
177 and the actual authentication data. Returns NULL on error. */
179 SilcBuffer silc_auth_public_key_auth_generate(SilcPKCS pkcs,
181 void *id, SilcIdType type)
183 unsigned char *random;
184 unsigned char auth_data[32];
185 unsigned int auth_len;
187 unsigned int tmp_len;
190 SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
192 /* Get 256 bytes of random data */
193 random = silc_rng_global_get_rn_data(256);
197 /* Encode the auth data */
198 tmp = silc_auth_public_key_encode_data(pkcs, random, 256, id, type,
203 /* Compute the hash and the signature. */
204 if (!silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
206 memset(random, 0, 256);
207 memset(tmp, 0, tmp_len);
213 /* Encode Authentication Payload */
214 buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, random, 256,
215 auth_data, auth_len);
217 memset(tmp, 0, tmp_len);
218 memset(auth_data, 0, sizeof(auth_data));
219 memset(random, 0, 256);
226 /* Verifies the authentication data. Returns TRUE if authentication was
229 int silc_auth_public_key_auth_verify(SilcAuthPayload payload,
230 SilcPKCS pkcs, SilcHash hash,
231 void *id, SilcIdType type)
234 unsigned int tmp_len;
236 SILC_LOG_DEBUG(("Verifying authentication data"));
238 /* Encode auth data */
239 tmp = silc_auth_public_key_encode_data(pkcs, payload->random_data,
243 SILC_LOG_DEBUG(("Authentication failed"));
247 /* Verify the authencation data */
248 if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->auth_data,
249 payload->auth_len, tmp, tmp_len)) {
251 memset(tmp, 0, tmp_len);
253 SILC_LOG_DEBUG(("Authentication failed"));
257 memset(tmp, 0, tmp_len);
260 SILC_LOG_DEBUG(("Authentication successfull"));
265 /* Same as above but the payload is not parsed yet. This will parse it. */
267 int silc_auth_public_key_auth_verify_data(SilcBuffer payload,
268 SilcPKCS pkcs, SilcHash hash,
269 void *id, SilcIdType type)
271 SilcAuthPayload auth_payload;
274 auth_payload = silc_auth_payload_parse(payload);
276 SILC_LOG_DEBUG(("Authentication failed"));
280 ret = silc_auth_public_key_auth_verify(auth_payload, pkcs, hash,
283 silc_auth_payload_free(auth_payload);