created.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 20 Feb 2001 18:14:18 +0000 (18:14 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 20 Feb 2001 18:14:18 +0000 (18:14 +0000)
lib/silccore/silcauth.c [new file with mode: 0644]
lib/silccore/silcauth.h [new file with mode: 0644]

diff --git a/lib/silccore/silcauth.c b/lib/silccore/silcauth.c
new file mode 100644 (file)
index 0000000..ba2f5c8
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+
+  silcauth.c
+
+  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+  Copyright (C) 2001 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+/* $Id$ */
+
+#include "silcincludes.h"
+#include "silcauth.h"
+
+/******************************************************************************
+
+                           Authentication Payload
+
+******************************************************************************/
+
+/* Authentication Payload structure */
+struct SilcAuthPayloadStruct {
+  unsigned short len;
+  unsigned short auth_method;
+  unsigned short random_len;
+  unsigned char *random_data;
+  unsigned short auth_len;
+  unsigned char *auth_data;
+};
+
+/* Parses and returns Authentication Payload */
+
+SilcAuthPayload silc_auth_payload_parse(SilcBuffer buffer)
+{
+  SilcAuthPayload new;
+  int ret;
+
+  SILC_LOG_DEBUG(("Parsing Authentication Payload"));
+
+  new = silc_calloc(1, sizeof(*new));
+
+  /* Parse the payload */
+  ret = silc_buffer_unformat(buffer, 
+                            SILC_STR_UI_SHORT(&new->len),
+                            SILC_STR_UI_CHAR(&new->auth_method),
+                            SILC_STR_UI16_NSTRING_ALLOC(&new->random_data,
+                                                        &new->random_len),
+                            SILC_STR_UI16_NSTRING_ALLOC(&new->auth_data,
+                                                        &new->auth_len),
+                            SILC_STR_END);
+  if (ret == -1) {
+    silc_free(new);
+    return NULL;
+  }
+
+  if (new->len != buffer->len) {
+    silc_auth_payload_free(new);
+    return NULL;
+  }
+
+  /* If password authentication, random data must not be set */
+  if (new->auth_method == SILC_AUTH_PASSWORD && new->random_len) {
+    silc_auth_payload_free(new);
+    return NULL;
+  }
+
+  return new;
+}
+
+/* Encodes authentication payload into buffer and returns it */
+
+SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
+                                   unsigned char *random_data,
+                                   unsigned short random_len,
+                                   unsigned char *auth_data,
+                                   unsigned short auth_len)
+{
+  SilcBuffer buffer;
+  unsigned int len;
+
+  SILC_LOG_DEBUG(("Encoding Authentication Payload"));
+
+  len = 4 + 4 + random_len + auth_len;
+  buffer = silc_buffer_alloc(len);
+  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  silc_buffer_format(buffer,
+                    SILC_STR_UI_SHORT(len),
+                    SILC_STR_UI_SHORT(method),
+                    SILC_STR_UI_SHORT(random_len),
+                    SILC_STR_UI_XNSTRING(random_data, random_len),
+                    SILC_STR_UI_SHORT(auth_len),
+                    SILC_STR_UI_XNSTRING(auth_data, auth_len),
+                    SILC_STR_END);
+
+  return buffer;
+}
+
+/* Frees authentication payload. */
+
+void silc_auth_payload_free(SilcAuthPayload payload)
+{
+  if (payload) {
+    if (payload->random_data) {
+      memset(payload->random_data, 0, payload->random_len);
+      silc_free(payload->random_data);
+    }
+    if (payload->auth_data) {
+      memset(payload->auth_data, 0, payload->auth_len);
+      silc_free(payload->auth_data);
+    }
+    silc_free(payload);
+  }
+}
+
+/******************************************************************************
+
+                           Authentication Routines
+
+******************************************************************************/
+
+/* Encodes the authentication data for hashing and signing as the protocol
+   dictates. */
+
+static unsigned char *
+silc_auth_public_key_encode(SilcPKCS pkcs, unsigned char *random,
+                           unsigned int random_len, unsigned int *ret_len)
+{
+  SilcBuffer buf;
+  unsigned char *pk, *ret;
+  unsigned int pk_len;
+
+  pk = silc_pkcs_get_public_key(pkcs, &pk_len);
+  if (!pk)
+    return NULL;
+
+  buf = silc_buffer_alloc(random_len + pk_len);
+  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  silc_buffer_format(buf,
+                    SILC_STR_UI_XNSTRING(random, random_len),
+                    SILC_STR_UI_XNSTRING(pk, pk_len),
+                    SILC_STR_END);
+  
+  ret = silc_calloc(buf->len, sizeof(*ret));
+  memcpy(ret, buf->data, buf->len);
+
+  if (ret_len)
+    *ret_len = buf->len;
+
+  silc_buffer_free(buf);
+  silc_free(pk);
+
+  return ret;
+}
+
+/* Generates Authentication Payload with authentication data. This is used
+   to do public key based authentication. This generates the random data
+   and the actual authentication data. Returns NULL on error. */
+
+SilcBuffer silc_auth_public_key_auth_generate(SilcPKCS pkcs,
+                                             SilcHash hash)
+{
+  unsigned char *random;
+  unsigned char auth_data[32];
+  unsigned int auth_len;
+  unsigned char *tmp;
+  unsigned int tmp_len;
+  SilcBuffer buf;
+
+  SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
+
+  /* Get 256 bytes of random data */
+  random = silc_rng_global_get_rn_data(256);
+  if (!random)
+    return NULL;
+  
+  /* Encode the auth data */
+  tmp = silc_auth_public_key_encode(pkcs, random, 256, &tmp_len);
+  if (!tmp)
+    return NULL;
+
+  /* Compute the hash and the signature. */
+  if (!silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
+                               &auth_len)) {
+    memset(random, 0, 256);
+    memset(tmp, 0, tmp_len);
+    silc_free(tmp);
+    silc_free(random);
+    return NULL;
+  }
+
+  /* Encode Authentication Payload */
+  buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, random, 256,
+                                auth_data, auth_len);
+
+  memset(tmp, 0, tmp_len);
+  memset(auth_data, 0, sizeof(auth_data));
+  memset(random, 0, 256);
+  silc_free(tmp);
+  silc_free(random);
+
+  return buf;
+}
+
+/* Verifies the authentication data. Returns TRUE if authentication was
+   successfull. */
+
+int silc_auth_public_key_auth_verify(SilcAuthPayload payload,
+                                    SilcPKCS pkcs, SilcHash hash)
+{
+  unsigned char *tmp;
+  unsigned int tmp_len;
+
+  SILC_LOG_DEBUG(("Verifying authentication data"));
+
+  /* Encode auth data */
+  tmp = silc_auth_public_key_encode(pkcs, payload->random_data, 
+                                   payload->random_len, &tmp_len);
+  if (!tmp) {
+    SILC_LOG_DEBUG(("Authentication failed"));
+    return FALSE;
+  }
+
+  /* Verify the authencation data */
+  if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->auth_data,
+                                 payload->auth_len, tmp, tmp_len)) {
+
+    memset(tmp, 0, tmp_len);
+    silc_free(tmp);
+    SILC_LOG_DEBUG(("Authentication failed"));
+    return FALSE;
+  }
+
+  memset(tmp, 0, tmp_len);
+  silc_free(tmp);
+
+  SILC_LOG_DEBUG(("Authentication successfull"));
+
+  return TRUE;
+}
+
+/* Same as above but the payload is not parsed yet. This will parse it. */
+
+int silc_auth_public_key_auth_verify_data(SilcBuffer payload,
+                                         SilcPKCS pkcs, SilcHash hash)
+{
+  SilcAuthPayload auth_payload;
+  int ret;
+
+  auth_payload = silc_auth_payload_parse(payload);
+  if (!auth_payload) {
+    SILC_LOG_DEBUG(("Authentication failed"));
+    return FALSE;
+  }
+
+  ret = silc_auth_public_key_auth_verify(auth_payload, pkcs, hash);
+
+  silc_auth_payload_free(auth_payload);
+
+  return ret;
+}
diff --git a/lib/silccore/silcauth.h b/lib/silccore/silcauth.h
new file mode 100644 (file)
index 0000000..a7a74a5
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+
+  siclauth.h
+
+  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+  Copyright (C) 2001 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+
+#ifndef SILCAUTH_H
+#define SILCAUTH_H
+
+/* Forward declaration of the Authentication Payload */
+typedef struct SilcAuthPayloadStruct *SilcAuthPayload;
+
+/* Authentication method type */
+typedef unsigned short SilcAuthMethod;
+
+/* Authentication methods in SILC protocol */
+#define SILC_AUTH_NONE        0
+#define SILC_AUTH_PASSWORD    1
+#define SILC_AUTH_PUBLIC_KEY  2
+
+/* Authentication protocol status message (used by all authentication
+   procols in the SILC). */
+#define SILC_AUTH_OK          0
+#define SILC_AUTH_FAILED      1
+
+/* Prototypes */
+SilcAuthPayload silc_auth_payload_parse(SilcBuffer buffer);
+SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
+                                   unsigned char *random_data,
+                                   unsigned short random_len,
+                                   unsigned char *auth_data,
+                                   unsigned short auth_len);
+void silc_auth_payload_free(SilcAuthPayload payload);
+SilcBuffer silc_auth_public_key_auth_generate(SilcPKCS pkcs,
+                                             SilcHash hash);
+int silc_auth_public_key_auth_verify(SilcAuthPayload paylaod,
+                                    SilcPKCS pkcs, SilcHash hash);
+int silc_auth_public_key_auth_verify_data(SilcBuffer payload,
+                                         SilcPKCS pkcs, SilcHash hash);
+
+#endif