* Removed the RNG kludge from lib/silcmath/primegen.c and changed
it to use the Global RNG API.
+ * Defined Authentication Payload into protocol specification that
+ is used during SILC session to authenticate entities. It is
+ used for example by client to authenticate itself to the server
+ to obtain server operator privileges.
+
+ Implemented this payload into the lib/silccore/silcauth.[ch].
+ Implemented also routines for public key based authentication
+ as the new protocol specification dictates.
+
+ Moved definitions of different authentication methods from
+ lib/silccore/silcprotocol.h into lib/silccore/silcauth.h.
+
+ * Added silc_pkcs_encrypt, silc_pkcs_decrypt, silc_pkcs_sign,
+ silc_pkcs_verify and silc_pkcs_sign_with_hash and
+ silc_pkcs_verify_with_hash functions into the file
+ lib/silccrypt/silcpkcs.[ch].
+
Mon Feb 19 19:59:28 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* The client entry's userinfo pointer must be always valid.
if (client) {
switch(client->auth_meth) {
- case SILC_PROTOCOL_CONN_AUTH_NONE:
+ case SILC_AUTH_NONE:
/* No authentication required */
SILC_LOG_DEBUG(("No authentication required"));
break;
- case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
+ case SILC_AUTH_PASSWORD:
/* Password authentication */
SILC_LOG_DEBUG(("Password authentication"));
ret = silc_server_password_authentication(server, auth_data,
return;
break;
- case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
+ case SILC_AUTH_PUBLIC_KEY:
/* Public key authentication */
SILC_LOG_DEBUG(("Public key authentication"));
ret = silc_server_public_key_authentication(server,
if (serv) {
switch(serv->auth_meth) {
- case SILC_PROTOCOL_CONN_AUTH_NONE:
+ case SILC_AUTH_NONE:
/* No authentication required */
SILC_LOG_DEBUG(("No authentication required"));
break;
- case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
+ case SILC_AUTH_PASSWORD:
/* Password authentication */
SILC_LOG_DEBUG(("Password authentication"));
ret = silc_server_password_authentication(server, auth_data,
return;
break;
- case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
+ case SILC_AUTH_PUBLIC_KEY:
/* Public key authentication */
SILC_LOG_DEBUG(("Public key authentication"));
ret = silc_server_public_key_authentication(server,
if (serv) {
switch(serv->auth_meth) {
- case SILC_PROTOCOL_CONN_AUTH_NONE:
+ case SILC_AUTH_NONE:
/* No authentication required */
SILC_LOG_DEBUG(("No authentication required"));
break;
- case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
+ case SILC_AUTH_PASSWORD:
/* Password authentication */
SILC_LOG_DEBUG(("Password authentication"));
ret = silc_server_password_authentication(server, auth_data,
return;
break;
- case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
+ case SILC_AUTH_PUBLIC_KEY:
/* Public key authentication */
SILC_LOG_DEBUG(("Public key authentication"));
ret = silc_server_public_key_authentication(server,
unsigned int auth_data_len = 0;
switch(ctx->auth_meth) {
- case SILC_PROTOCOL_CONN_AUTH_NONE:
+ case SILC_AUTH_NONE:
/* No authentication required */
break;
- case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
+ case SILC_AUTH_PASSWORD:
/* Password authentication */
if (ctx->auth_data && ctx->auth_data_len) {
auth_data = ctx->auth_data;
break;
- case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
+ case SILC_AUTH_PUBLIC_KEY:
/* Public key authentication */
/* XXX TODO */
break;
*/
unsigned char ok[4];
- SILC_PUT32_MSB(SILC_CONN_AUTH_OK, ok);
+ SILC_PUT32_MSB(SILC_AUTH_OK, ok);
/* Authentication failed */
silc_server_packet_send(server, ctx->sock, SILC_PACKET_SUCCESS,
*/
unsigned char error[4];
- SILC_PUT32_MSB(SILC_CONN_AUTH_FAILED, error);
+ SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
/* Authentication failed */
silc_server_packet_send(server, ctx->sock, SILC_PACKET_FAILURE,
proto_ctx->dest_id = ctx->dest_id;
/* Resolve the authentication method used in this connection */
- proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ proto_ctx->auth_meth = SILC_AUTH_PASSWORD;
if (server->config->routers) {
SilcConfigServerSectionServerConnection *conn = NULL;
}
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->clients->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ config->clients->auth_meth = SILC_AUTH_PASSWORD;
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->clients->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+ config->clients->auth_meth = SILC_AUTH_PUBLIC_KEY;
silc_free(tmp);
}
}
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->servers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ config->servers->auth_meth = SILC_AUTH_PASSWORD;
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->servers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+ config->servers->auth_meth = SILC_AUTH_PUBLIC_KEY;
silc_free(tmp);
}
}
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->routers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ config->routers->auth_meth = SILC_AUTH_PASSWORD;
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->routers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+ config->routers->auth_meth = SILC_AUTH_PUBLIC_KEY;
silc_free(tmp);
}
}
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->admins->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ config->admins->auth_meth = SILC_AUTH_PASSWORD;
if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->admins->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+ config->admins->auth_meth = SILC_AUTH_PUBLIC_KEY;
silc_free(tmp);
}
connection authentication protocol is described in detail in [SILC3].
+.ti 0
+3.9.1 Authentication Payload
+
+Authentication payload is used separately from the SKE and the Connection
+authentication protocol. It is used during the session to authenticate
+with the remote. For example, the client can authenticate itself to the
+server to be server operator. In this case, Authentication Payload is
+used.
+
+The format of the Authentication Payload is as follows:
+
+
+.in 5
+.nf
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Payload Length | Authentication Method |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Public Data Length | |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| |
+~ Public Data ~
+| |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Authentication Data Length | |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| |
+~ Authentication Data ~
+| |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|
+.in 3
+
+.ce
+Figure 5: Authentication Payload
+
+
+.in 6
+o Payload Length (2 bytes) - Length of the entire payload.
+
+o Authentication Type (2) - The method of the authentication.
+ The authentication methods are defined in [SILC2] in the
+ Connection Auth Request Payload. The NONE authentication
+ method is not recommended.
+
+o Public Data Length (2 bytes) - Indicates the length of
+ the Public Data field.
+
+o Public Data (variable length) - This is defined only if
+ the authentication method is public key. If it is any other
+ this field does not exist and the Public Data Length field
+ is set to zero (0).
+
+ When the authentication method is public key this includes
+ 128 to 4096 bytes of non-zero random data that is used in
+ the signature process, described subsequently.
+
+o Authentication Data Length (2 bytes) - Indicates the
+ length of the Authentication Data field.
+
+o Authentication Data (variable length) - Authentication
+ method dependent authentication data.
+.in 3
+
+
+If the authentication method is password based, the Authentication
+Data field includes the plaintext password. It is safe to send
+plaintext password since the entire payload is encrypted.
+
+If the authentication method is public key based (or certificate)
+the Authentication Data is computed as follows:
+
+ HASH = hash(random bytes | public key (or certificate));
+ Authentication Data = sign(HASH);
+
+The hash() and sign() are the hash funtion and the public key cryptography
+function selected in the SKE protocol. The public key is SILC style
+public key unless certificates are used. The random bytes are non-zero
+random bytes of length between 128 and 4096 bytes, and will be included
+into the Public Data field as is. The receiver will compute the signature
+using the random data received in the payload and the public key (or
+certificate) received in the SKE protocol. After computing the receiver
+must verify the signature. In this case also, the entire payload is
+encrypted.
+
+
.ti 0
3.10 Algorithms
#include "silcpacket.h"
#include "silcnotify.h"
#include "silcmode.h"
+#include "silcauth.h"
/* TRQ (SilcList API and SilcDList API) */
#include "silclist.h"
&proto_ctx->auth_data_len))
{
/* XXX do AUTH_REQUEST resolcing with server */
- proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
+ proto_ctx->auth_meth = SILC_AUTH_NONE;
}
/* Free old protocol as it is finished now */
unsigned int auth_data_len = 0;
switch(ctx->auth_meth) {
- case SILC_PROTOCOL_CONN_AUTH_NONE:
+ case SILC_AUTH_NONE:
/* No authentication required */
break;
- case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
+ case SILC_AUTH_PASSWORD:
/* Password authentication */
if (ctx->auth_data && ctx->auth_data_len) {
auth_data = ctx->auth_data;
auth_data_len = strlen(auth_data);
break;
- case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
+ case SILC_AUTH_PUBLIC_KEY:
/* XXX */
break;
}
*/
unsigned char error[4];
- SILC_PUT32_MSB(SILC_CONN_AUTH_FAILED, error);
+ SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
/* Error in protocol. Send FAILURE packet. Although I don't think
this could ever happen on client side. */
silcsockconn.c \
silcpayload.c \
silcnotify.c \
- silcmode.c
+ silcmode.c \
+ silcauth.c
EXTRA_DIST = *.h
#define SILC_PROTOCOL_STATE_FAILURE 253 /* Received failure from remote */
#define SILC_PROTOCOL_STATE_ERROR 254 /* Local error at our end */
-/* Connection Authentication protocols' authentication methods */
-#define SILC_PROTOCOL_CONN_AUTH_NONE 0
-#define SILC_PROTOCOL_CONN_AUTH_PASSWORD 1
-#define SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY 2
-
-/* XXX These don't belong here really! */
-/* Connection authentication protocol status message */
-#define SILC_CONN_AUTH_OK 0
-#define SILC_CONN_AUTH_FAILED 1
-
/* Type definition for above auth methods */
typedef unsigned char SilcProtocolAuthMeth;
return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
}
+/* Encrypts */
+
+int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len)
+{
+ return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
+}
+
+/* Decrypts */
+
+int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len)
+{
+ return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
+}
+
+/* Generates signature */
+
+int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len)
+{
+ return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
+}
+
+/* Verifies signature */
+
+int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
+ unsigned int signature_len, unsigned char *data,
+ unsigned int data_len)
+{
+ return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
+ data, data_len);
+}
+
+/* Generates signature with hash. The hash is signed. */
+
+int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
+ unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len)
+{
+ unsigned char hashr[32];
+ unsigned int hash_len;
+ int ret;
+
+ silc_hash_make(hash, src, src_len, hashr);
+ hash_len = hash->hash->hash_len;
+
+ ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
+ memset(hashr, 0, sizeof(hashr));
+
+ return ret;
+}
+
+/* Verifies signature with hash. The `data' is hashed and verified against
+ the `signature'. */
+
+int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
+ unsigned char *signature,
+ unsigned int signature_len,
+ unsigned char *data,
+ unsigned int data_len)
+{
+ unsigned char hashr[32];
+ unsigned int hash_len;
+ int ret;
+
+ silc_hash_make(hash, data, data_len, hashr);
+ hash_len = hash->hash->hash_len;
+
+ ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
+ hashr, hash_len);
+ memset(hashr, 0, sizeof(hashr));
+
+ return ret;
+}
+
/* Encodes and returns SILC public key identifier. If some of the
arguments is NULL those are not encoded into the identifier string.
Protocol says that at least username and host must be provided. */
int silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key);
int silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
unsigned int prv_len);
+int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len);
+int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len);
+int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len);
+int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
+ unsigned int signature_len, unsigned char *data,
+ unsigned int data_len);
+int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
+ unsigned char *src, unsigned int src_len,
+ unsigned char *dst, unsigned int *dst_len);
+int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
+ unsigned char *signature,
+ unsigned int signature_len,
+ unsigned char *data,
+ unsigned int data_len);
char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
char *email, char *org, char *country);
SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,