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(SilcPKCS pkcs, unsigned char *random,
136 unsigned int random_len, unsigned int *ret_len)
139 unsigned char *pk, *ret;
142 pk = silc_pkcs_get_public_key(pkcs, &pk_len);
146 buf = silc_buffer_alloc(random_len + pk_len);
147 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
148 silc_buffer_format(buf,
149 SILC_STR_UI_XNSTRING(random, random_len),
150 SILC_STR_UI_XNSTRING(pk, pk_len),
153 ret = silc_calloc(buf->len, sizeof(*ret));
154 memcpy(ret, buf->data, buf->len);
159 silc_buffer_free(buf);
165 /* Generates Authentication Payload with authentication data. This is used
166 to do public key based authentication. This generates the random data
167 and the actual authentication data. Returns NULL on error. */
169 SilcBuffer silc_auth_public_key_auth_generate(SilcPKCS pkcs,
172 unsigned char *random;
173 unsigned char auth_data[32];
174 unsigned int auth_len;
176 unsigned int tmp_len;
179 SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
181 /* Get 256 bytes of random data */
182 random = silc_rng_global_get_rn_data(256);
186 /* Encode the auth data */
187 tmp = silc_auth_public_key_encode(pkcs, random, 256, &tmp_len);
191 /* Compute the hash and the signature. */
192 if (!silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
194 memset(random, 0, 256);
195 memset(tmp, 0, tmp_len);
201 /* Encode Authentication Payload */
202 buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, random, 256,
203 auth_data, auth_len);
205 memset(tmp, 0, tmp_len);
206 memset(auth_data, 0, sizeof(auth_data));
207 memset(random, 0, 256);
214 /* Verifies the authentication data. Returns TRUE if authentication was
217 int silc_auth_public_key_auth_verify(SilcAuthPayload payload,
218 SilcPKCS pkcs, SilcHash hash)
221 unsigned int tmp_len;
223 SILC_LOG_DEBUG(("Verifying authentication data"));
225 /* Encode auth data */
226 tmp = silc_auth_public_key_encode(pkcs, payload->random_data,
227 payload->random_len, &tmp_len);
229 SILC_LOG_DEBUG(("Authentication failed"));
233 /* Verify the authencation data */
234 if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->auth_data,
235 payload->auth_len, tmp, tmp_len)) {
237 memset(tmp, 0, tmp_len);
239 SILC_LOG_DEBUG(("Authentication failed"));
243 memset(tmp, 0, tmp_len);
246 SILC_LOG_DEBUG(("Authentication successfull"));
251 /* Same as above but the payload is not parsed yet. This will parse it. */
253 int silc_auth_public_key_auth_verify_data(SilcBuffer payload,
254 SilcPKCS pkcs, SilcHash hash)
256 SilcAuthPayload auth_payload;
259 auth_payload = silc_auth_payload_parse(payload);
261 SILC_LOG_DEBUG(("Authentication failed"));
265 ret = silc_auth_public_key_auth_verify(auth_payload, pkcs, hash);
267 silc_auth_payload_free(auth_payload);