summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-10-03 09:03:04 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-10-03 09:03:04 +0000
commitba5f98458a434d0b3c13ed1f5fdb14aac328faa7 (patch)
tree6b8fb84062858b1533dabe0f1c6d88f563894beb
parent91a1dc4084213200c2618dde1225746f2c8619a5 (diff)
downloadgnutls-ba5f98458a434d0b3c13ed1f5fdb14aac328faa7.tar.gz
*** empty log message ***
-rw-r--r--libextra/gnutls_openpgp.c2107
1 files changed, 0 insertions, 2107 deletions
diff --git a/libextra/gnutls_openpgp.c b/libextra/gnutls_openpgp.c
deleted file mode 100644
index 824fd99375..0000000000
--- a/libextra/gnutls_openpgp.c
+++ /dev/null
@@ -1,2107 +0,0 @@
-/*
- * Copyright (C) 2002 Timo Schulz <twoaday@freakmail.de>
- *
- * This file is part of GNUTLS.
- *
- * GNUTLS-EXTRA 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.
- *
- * GNUTLS-EXTRA 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "gnutls_int.h"
-#include "gnutls_errors.h"
-#include "gnutls_mpi.h"
-#include "gnutls_cert.h"
-#include "gnutls_datum.h"
-#include "gnutls_global.h"
-#include "auth_cert.h"
-#include "gnutls_openpgp.h"
-
-#ifdef HAVE_LIBOPENCDK
-#include <gnutls/compat8.h>
-#include <gnutls_str.h>
-#include <stdio.h>
-#include <gcrypt.h>
-#include <opencdk.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <assert.h>
-
-#define OPENPGP_NAME_SIZE 256
-
-#define datum_append(x, y, z) _gnutls_datum_append_m( x, y, z, gnutls_realloc )
-
-typedef struct {
- int type;
- int armored;
- size_t size;
- uint8 *data;
-} keybox_blob;
-
-typedef enum {
- KBX_BLOB_FILE = 0x00,
- KBX_BLOB_DATA = 0x01
-} keyring_blob_types;
-
-
-static void
-release_mpi_array( GNUTLS_MPI *arr, size_t n )
-{
- GNUTLS_MPI x;
-
- while( arr && n-- ) {
- x = *arr;
- _gnutls_mpi_release( &x );
- *arr = NULL; arr++;
- }
-}
-
-
-int
-_gnutls_map_cdk_rc( int rc )
-{
- switch( rc ) {
- case CDK_Success: return 0;
- case CDK_General_Error: return GNUTLS_E_INTERNAL_ERROR;
- case CDK_File_Error: return GNUTLS_E_FILE_ERROR;
- case CDK_MPI_Error: return GNUTLS_E_MPI_SCAN_FAILED;
- case CDK_Error_No_Key: return GNUTLS_E_OPENPGP_GETKEY_FAILED;
- case CDK_Wrong_Format: return GNUTLS_E_OPENPGP_TRUSTDB_VERSION_UNSUPPORTED;
- case CDK_Armor_Error: return GNUTLS_E_BASE64_DECODING_ERROR;
- case CDK_Inv_Value: return GNUTLS_E_INVALID_REQUEST;
- default: return GNUTLS_E_INTERNAL_ERROR;
- }
- return rc;
-}
-
-
-static unsigned long
-buftou32( const uint8 *buf )
-{
- unsigned a;
- a = buf[0] << 24;
- a |= buf[1] << 16;
- a |= buf[2] << 8;
- a |= buf[3];
- return a;
-}
-
-
-static int
-kbx_blob_new( keybox_blob **r_ctx )
-{
- keybox_blob *c;
-
- if( !r_ctx ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- c = cdk_calloc( 1, sizeof * c );
- if( !c ) {
- gnutls_assert( );
- return GNUTLS_E_MEMORY_ERROR;
- }
- *r_ctx = c;
-
- return 0;
-}
-
-
-static void
-kbx_blob_release( keybox_blob *ctx )
-{
- if( ctx ) {
- cdk_free( ctx->data );
- cdk_free( ctx );
- }
-}
-
-
-static CDK_KEYDB_HD
-kbx_to_keydb( keybox_blob *blob )
-{
- CDK_KEYDB_HD hd;
- int rc;
-
- if( !blob ) {
- gnutls_assert( );
- return NULL;
- }
-
- switch( blob->type ) {
- case KBX_BLOB_FILE:
- rc = cdk_keydb_new( &hd, blob->armored? CDK_DBTYPE_ARMORED:
- CDK_DBTYPE_KEYRING, blob->data, blob->size );
- break;
-
- case KBX_BLOB_DATA:
- rc = cdk_keydb_new( &hd, CDK_DBTYPE_DATA, blob->data, blob->size );
- break;
-
- default:
- rc = GNUTLS_E_INTERNAL_ERROR;
- gnutls_assert( );
- break;
- }
- if( rc )
- hd = NULL;
- return hd;
-}
-
-
-/* Extract a keybox blob from the given position. */
-static keybox_blob*
-kbx_read_blob( const gnutls_datum* keyring, size_t pos )
-{
- keybox_blob *blob = NULL;
- int rc;
-
- if( !keyring || !keyring->data || pos > keyring->size ) {
- gnutls_assert( );
- return NULL;
- }
-
- rc = kbx_blob_new( &blob );
- if( rc )
- return NULL;
-
- blob->type = keyring->data[pos];
- if( blob->type != KBX_BLOB_FILE && blob->type != KBX_BLOB_DATA ) {
- kbx_blob_release( blob );
- return NULL;
- }
- blob->armored = keyring->data[pos + 1];
- blob->size = buftou32( keyring->data + pos + 2 );
- if( !blob->size ) {
- kbx_blob_release( blob );
- return NULL;
- }
- blob->data = cdk_calloc( 1, blob->size + 1 );
- if( !blob->data )
- return NULL;
- memcpy( blob->data, keyring->data + (pos + 6), blob->size );
- blob->data[blob->size] = '\0';
-
- return blob;
-}
-
-
-/* Creates a keyring blob from raw data
- *
- * Format:
- * 1 octet type
- * 1 octet armored
- * 4 octet size of blob
- * n octets data
- */
-static uint8*
-kbx_data_to_keyring( int type, int enc, const char *data,
- size_t size, size_t *r_size )
-{
- uint8 *p = NULL;
-
- if( !data )
- return NULL;
-
- p = gnutls_malloc( 1+4+size );
- if( !p )
- return NULL;
- p[0] = type; /* type: {keyring,name} */
- p[1] = enc; /* encoded: {plain, armored} */
- p[2] = size >> 24;
- p[3] = size >> 16;
- p[4] = size >> 8;
- p[5] = size ;
- memcpy( p + 6, data, size );
- if( r_size )
- *r_size = 6 + size;
- return p;
-}
-
-
-CDK_PACKET*
-search_packet( const gnutls_datum *buf, int pkttype )
-{
- static CDK_KBNODE knode = NULL;
- CDK_PACKET *pkt;
-
- if( !buf && !pkttype ) {
- cdk_kbnode_release( knode );
- knode = NULL;
- return NULL;
- }
- if( cdk_kbnode_read_from_mem( &knode, buf->data, buf->size ) )
- return NULL;
- pkt = cdk_kbnode_find_packet( knode, pkttype );
-
- return pkt;
-}
-
-
-static int
-stream_to_datum( CDK_STREAM inp, gnutls_datum *raw )
-{
- uint8 buf[4096];
- int rc = 0, nread, nbytes = 0;
-
- if( !buf || !raw ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- cdk_stream_seek( inp, 0 );
- while( !cdk_stream_eof( inp ) ) {
- nread = cdk_stream_read( inp, buf, sizeof buf-1 );
- if( nread == EOF )
- break;
- datum_append( raw, buf, nread );
- nbytes += nread;
- }
- cdk_stream_seek( inp, 0 );
- if( !nbytes )
- rc = GNUTLS_E_INTERNAL_ERROR;
-
- return rc;
-}
-
-
-static int
-openpgp_pk_to_gnutls_cert( gnutls_cert *cert, cdkPKT_public_key *pk )
-{
- uint8 buf[512];
- size_t nbytes = 0;
- int algo, i;
- int rc = 0;
-
- if( !cert || !pk ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* GnuTLS OpenPGP doesn't support ELG keys */
- if( is_ELG(pk->pubkey_algo) )
- return GNUTLS_E_UNWANTED_ALGORITHM;
-
- algo = is_DSA( pk->pubkey_algo )? GNUTLS_PK_DSA : GNUTLS_PK_RSA;
- cert->subject_pk_algorithm = algo;
- cert->version = pk->version;
- cert->cert_type = GNUTLS_CRT_OPENPGP;
-
- if( is_DSA(pk->pubkey_algo) || pk->pubkey_algo == GCRY_PK_RSA_S )
- cert->keyUsage = KEY_DIGITAL_SIGNATURE;
- else if( pk->pubkey_algo == GCRY_PK_RSA_E )
- cert->keyUsage = KEY_ENCIPHER_ONLY;
- else if( pk->pubkey_algo == GCRY_PK_RSA )
- cert->keyUsage = KEY_DIGITAL_SIGNATURE
- | KEY_ENCIPHER_ONLY;
-
- cert->params_size = cdk_pk_get_npkey( pk->pubkey_algo );
- for( i = 0; i < cert->params_size; i++ ) {
- nbytes = sizeof buf-1;
- cdk_pk_get_mpi( pk, i, buf, &nbytes, NULL );
- rc = _gnutls_mpi_scan_pgp( &cert->params[i], buf, &nbytes );
- if( rc ) {
- rc = GNUTLS_E_MPI_SCAN_FAILED;
- break;
- }
- }
-
- if( rc )
- release_mpi_array( cert->params, i-1 );
- return rc;
-}
-
-/*-
- * _gnutls_openpgp_key2gnutls_key - Converts an OpenPGP secret key to GnuTLS
- * @pkey: the GnuTLS private key context to store the key.
- * @raw_key: the raw data which contains the whole key packets.
- *
- * The RFC2440 (OpenPGP Message Format) data is converted into the
- * GnuTLS specific data which is need to perform secret key operations.
- -*/
-int
-_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
- gnutls_datum *raw_key )
-{
- CDK_KBNODE snode;
- CDK_PACKET *pkt;
- CDK_STREAM out;
- cdkPKT_secret_key *sk = NULL;
- int pke_algo, i, j;
- size_t nbytes = 0;
- uint8 buf[512];
- int rc = 0;
-
- if( !pkey || raw_key->size <= 0 ) {
- gnutls_assert( );
- return GNUTLS_E_CERTIFICATE_ERROR;
- }
-
- out = cdk_stream_tmp( );
- if( !out )
- return GNUTLS_E_CERTIFICATE_ERROR;
- cdk_stream_write( out, raw_key->data, raw_key->size );
- cdk_stream_seek( out, 0 );
-
- cdk_keydb_get_keyblock( out, &snode );
- if( !snode ) {
- rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
- goto leave;
- }
-
- pkt = cdk_kbnode_find_packet( snode, CDK_PKT_SECRET_KEY );
- if( !pkt ) {
- rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
- goto leave;
- }
- sk = pkt->pkt.secret_key;
- pke_algo = sk->pk->pubkey_algo;
- pkey->params_size = cdk_pk_get_npkey( pke_algo );
- for( i = 0; i < pkey->params_size; i++ ) {
- nbytes = sizeof buf -1;
- cdk_pk_get_mpi( sk->pk, i, buf, &nbytes, NULL );
- rc = _gnutls_mpi_scan_pgp( &pkey->params[i], buf, &nbytes );
- if( rc ) {
- rc = GNUTLS_E_MPI_SCAN_FAILED;
- release_mpi_array( pkey->params, i-1 );
- goto leave;
- }
- }
- pkey->params_size += cdk_pk_get_nskey( pke_algo );
- for( j = 0; j < cdk_pk_get_nskey( pke_algo ); j++, i++ ) {
- nbytes = sizeof buf-1;
- cdk_sk_get_mpi( sk, j, buf, &nbytes, NULL );
- rc = _gnutls_mpi_scan_pgp( &pkey->params[i], buf, &nbytes );
- if ( rc ) {
- rc = GNUTLS_E_MPI_SCAN_FAILED;
- release_mpi_array( pkey->params, i-1 );
- goto leave;
- }
- }
-
- if( is_ELG(pke_algo) )
- return GNUTLS_E_UNWANTED_ALGORITHM;
- else if( is_DSA(pke_algo) )
- pkey->pk_algorithm = GNUTLS_PK_DSA;
- else if( is_RSA(pke_algo) )
- pkey->pk_algorithm = GNUTLS_PK_RSA;
-
-leave:
- cdk_stream_close( out );
- cdk_kbnode_release( snode );
- return rc;
-}
-
-
-/*-
- * _gnutls_openpgp_cert2gnutls_cert - Converts raw OpenPGP data to GnuTLS certs
- * @cert: the certificate to store the data.
- * @raw: the buffer which contains the whole OpenPGP key packets.
- *
- * The RFC2440 (OpenPGP Message Format) data is converted to a GnuTLS
- * specific certificate.
- -*/
-int
-_gnutls_openpgp_cert2gnutls_cert( gnutls_cert *cert, const gnutls_datum *raw )
-{
- CDK_KBNODE knode = NULL;
- CDK_PACKET *pkt = NULL;
- int rc;
-
- if( !cert ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- memset( cert, 0, sizeof *cert );
-
- rc = cdk_kbnode_read_from_mem( &knode, raw->data, raw->size );
- if( !(rc = _gnutls_map_cdk_rc( rc )) )
- pkt = cdk_kbnode_find_packet( knode, CDK_PKT_PUBLIC_KEY );
- if( !pkt )
- rc = GNUTLS_E_INTERNAL_ERROR;
- if( !rc )
- rc = _gnutls_set_datum( &cert->raw, raw->data, raw->size );
- if( !rc )
- rc = openpgp_pk_to_gnutls_cert( cert, pkt->pkt.public_key );
-
- cdk_kbnode_release( knode );
- return rc;
-}
-
-
-/*-
- * gnutls_openpgp_get_key - Retrieve a key from the keyring.
- * @key: the destination context to save the key.
- * @keyring: the datum struct that contains all keyring information.
- * @attr: The attribute (keyid, fingerprint, ...).
- * @by: What attribute is used.
- *
- * This function can be used to retrieve keys by different pattern
- * from a binary or a file keyring.
- -*/
-int
-gnutls_openpgp_get_key( gnutls_datum *key, const gnutls_datum *keyring,
- key_attr_t by, opaque *pattern )
-{
- keybox_blob *blob = NULL;
- CDK_KEYDB_HD hd = NULL;
- CDK_KBNODE knode = NULL;
- CDK_DBSEARCH ks = NULL;
- unsigned long keyid[2];
- unsigned char *buf;
- void * desc;
- size_t len;
- int rc = 0;
-
- if( !key || !keyring || by == KEY_ATTR_NONE ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- memset( key, 0, sizeof *key );
- blob = kbx_read_blob( keyring, 0 );
- if( !blob )
- return GNUTLS_E_MEMORY_ERROR;
- hd = kbx_to_keydb( blob );
-
- if( by == KEY_ATTR_SHORT_KEYID ) {
- keyid[0] = buftou32( pattern );
- desc = keyid;
- }
- else if( by == KEY_ATTR_KEYID ) {
- keyid[0] = buftou32( pattern );
- keyid[1] = buftou32( pattern + 4 );
- desc = keyid;
- }
- else
- desc = pattern;
- rc = cdk_keydb_search_new( &ks, by, desc );
- if( rc ) {
- rc = _gnutls_map_cdk_rc( rc );
- goto leave;
- }
-
- rc = cdk_keydb_search( hd, ks, &knode );
- if( rc ) {
- rc = _gnutls_map_cdk_rc( rc );
- goto leave;
- }
-
- if( !cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY ) ) {
- rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
- goto leave;
- }
-
- len = 20000;
- buf = cdk_calloc (1, len + 1);
- rc = cdk_kbnode_write_to_mem( knode, buf, &len );
- if( !rc )
- datum_append( key, buf, len );
- cdk_free( buf );
-
-leave:
- cdk_free( hd );
- cdk_kbnode_release( knode );
- cdk_keydb_search_free( ks );
- kbx_blob_release( blob );
- return rc;
-}
-
-
-int
-gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
- gnutls_datum *cert,
- gnutls_datum *key )
-{
- gnutls_datum raw;
- CDK_KBNODE knode = NULL, ctx = NULL, p;
- CDK_PACKET *pkt;
- int i = 0;
- int rc = 0;
-
- if ( !res || !key || !cert ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- rc = cdk_kbnode_read_from_mem( &knode, cert->data, cert->size );
- if( (rc = _gnutls_map_cdk_rc( rc )) )
- goto leave;
-
- /* fixme: too much duplicated code from (set_openpgp_key_file) */
- res->cert_list = gnutls_realloc_fast(res->cert_list,
- (1+res->ncerts)*sizeof(gnutls_cert*));
- if (res->cert_list == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- res->cert_list_length = gnutls_realloc_fast(res->cert_list_length,
- (1+res->ncerts)*sizeof(int));
- if (res->cert_list_length == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- res->cert_list[res->ncerts] = gnutls_calloc(1, sizeof(gnutls_cert));
- if (res->cert_list[res->ncerts] == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- i = 1;
- while( (p = cdk_kbnode_walk( knode, &ctx, 0 )) ) {
- pkt = cdk_kbnode_get_packet( p );
- if( i > MAX_PUBLIC_PARAMS_SIZE )
- break;
- if( pkt->pkttype == CDK_PKT_PUBLIC_KEY ) {
- int n = res->ncerts;
- cdkPKT_public_key *pk = pkt->pkt.public_key;
- res->cert_list_length[n] = 1;
- if (_gnutls_set_datum( &res->cert_list[n][0].raw,
- cert->data, cert->size ) < 0) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- openpgp_pk_to_gnutls_cert( &res->cert_list[n][0], pk );
- i++;
- }
- }
-
- res->ncerts++;
- res->pkey = gnutls_realloc_fast(res->pkey,
- (res->ncerts)*sizeof(gnutls_privkey));
- if( !res->pkey ) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- /* ncerts has been incremented before */
- rc = _gnutls_set_datum( &raw, key->data, key->size );
- if (rc < 0) {
- gnutls_assert();
- return rc;
- }
- rc = _gnutls_openpgp_key2gnutls_key( &res->pkey[res->ncerts-1], &raw );
- _gnutls_free_datum(&raw);
-
-leave:
- cdk_kbnode_release( knode );
-
- return rc;
-}
-
-
-/**
- * gnutls_certificate_set_openpgp_key_file - Used to set OpenPGP keys
- * @res: the destination context to save the data.
- * @CERTFILE: the file that contains the public key.
- * @KEYFILE: the file that contains the secret key.
- *
- * This funtion is used to load OpenPGP keys into the GnuTLS structure.
- * It doesn't matter whether the keys are armored or but, but the files
- * should only contain one key which should not be encrypted.
- **/
-int
-gnutls_certificate_set_openpgp_key_file( gnutls_certificate_credentials res,
- char* CERTFILE,
- char* KEYFILE )
-{
- struct stat statbuf;
- CDK_STREAM inp = NULL;
- CDK_KBNODE knode = NULL, ctx = NULL, p;
- CDK_PACKET *pkt = NULL;
- gnutls_datum raw;
- int i = 0, n;
- int rc = 0;
-
- if( !res || !KEYFILE || !CERTFILE ) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- if( stat( CERTFILE, &statbuf ) || stat( KEYFILE, &statbuf ) ) {
- gnutls_assert();
- return GNUTLS_E_FILE_ERROR;
- }
-
- rc = cdk_stream_open( CERTFILE, &inp );
- if( rc ) {
- gnutls_assert();
- return _gnutls_map_cdk_rc( rc );
- }
-
- if( cdk_armor_filter_use( inp ) )
- cdk_stream_set_armor_flag( inp, 0 );
-
- n = (1 + res->ncerts) * sizeof (gnutls_cert*);
- res->cert_list = gnutls_realloc_fast( res->cert_list, n );
- if( !res->cert_list ) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- n = (1 + res->ncerts) * sizeof (int);
- res->cert_list_length = gnutls_realloc_fast( res->cert_list_length, n );
- if( !res->cert_list_length ) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- res->cert_list[res->ncerts] = gnutls_calloc( 1, sizeof(gnutls_cert) );
- if( !res->cert_list[res->ncerts] ) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- while( !rc ) {
- i = 1;
- rc = cdk_keydb_get_keyblock( inp, &knode );
- while( knode && (p = cdk_kbnode_walk( knode, &ctx, 0 )) ) {
- if( i > MAX_PUBLIC_PARAMS_SIZE )
- break;
- pkt = cdk_kbnode_get_packet( p );
- if( pkt->pkttype == CDK_PKT_PUBLIC_KEY ) {
- int n = res->ncerts;
- cdkPKT_public_key *pk = pkt->pkt.public_key;
- res->cert_list_length[n] = 1;
- stream_to_datum( inp, &res->cert_list[n][0].raw );
- openpgp_pk_to_gnutls_cert( &res->cert_list[n][0], pk );
- i++;
- }
- }
- }
- if( rc == CDK_EOF && i > 1 )
- rc = 0;
- cdk_stream_close( inp );
- if( rc ) {
- cdk_kbnode_release( knode );
-
- gnutls_assert();
- rc = _gnutls_map_cdk_rc( rc );
- goto leave;
- }
- cdk_kbnode_release( knode );
-
- rc = cdk_stream_open( KEYFILE, &inp );
- if( rc ) {
- gnutls_assert();
- return _gnutls_map_cdk_rc( rc );
- }
- if( cdk_armor_filter_use( inp ) )
- cdk_stream_set_armor_flag( inp, 0 );
-
- memset( &raw, 0, sizeof raw );
- stream_to_datum( inp, &raw );
- cdk_stream_close( inp );
-
- n = (res->ncerts + 1) * sizeof (gnutls_privkey);
- res->pkey = gnutls_realloc_fast( res->pkey, n );
- if( !res->pkey ) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- res->ncerts++;
- /* ncerts has been incremented before */
- rc = _gnutls_openpgp_key2gnutls_key( &res->pkey[res->ncerts-1], &raw );
-
- leave:
- return rc;
-}
-
-
-int
-gnutls_openpgp_count_key_names( const gnutls_datum *cert )
-{
- CDK_KBNODE knode, p, ctx = NULL;
- CDK_PACKET *pkt;
- int nuids = 0;
-
- if( cert == NULL ) {
- gnutls_assert();
- return 0;
- }
- if( cdk_kbnode_read_from_mem( &knode, cert->data, cert->size ) ) {
- gnutls_assert();
- return 0;
- }
- while( (p = cdk_kbnode_walk( knode, &ctx, 0 )) ) {
- pkt = cdk_kbnode_get_packet( p );
- if( pkt->pkttype == CDK_PKT_USER_ID )
- nuids++;
- }
-
- return nuids;
-}
-
-
-/**
- * gnutls_openpgp_extract_key_name - Extracts the userID
- * @cert: the raw data that contains the OpenPGP public key.
- * @idx: the index of the ID to extract
- * @dn: the structure to store the userID specific data in.
- *
- * Extracts the userID from the raw OpenPGP key.
- **/
-int
-gnutls_openpgp_extract_key_name( const gnutls_datum *cert,
- int idx,
- gnutls_openpgp_name *dn )
-{
- CDK_KBNODE knode = NULL, ctx = NULL, p;
- CDK_PACKET *pkt = NULL;
- cdkPKT_user_id *uid = NULL;
- char *email;
- int pos = 0, pos1 = 0, pos2 = 0;
- size_t size = 0;
- int rc = 0;
-
- if( !cert || !dn ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- if( idx < 0 || idx > gnutls_openpgp_count_key_names( cert ) ) {
- gnutls_assert( );
- return GNUTLS_E_INTERNAL_ERROR;
- }
-
- memset( dn, 0, sizeof *dn );
- rc = cdk_kbnode_read_from_mem( &knode, cert->data, cert->size );
- if( (rc = _gnutls_map_cdk_rc( rc )) ) {
- gnutls_assert( );
- return rc;
- }
- if( !idx )
- pkt = cdk_kbnode_find_packet( knode, CDK_PKT_USER_ID );
- else {
- pos = 0;
- while( (p = cdk_kbnode_walk( knode, &ctx, 0 )) ) {
- pkt = cdk_kbnode_get_packet( p );
- if( pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx )
- break;
- }
- }
-
- if( !pkt ) {
- rc = GNUTLS_E_INTERNAL_ERROR;
- goto leave;
- }
-
- uid = pkt->pkt.user_id;
- size = uid->len < OPENPGP_NAME_SIZE? uid->len : OPENPGP_NAME_SIZE-1;
- memcpy( dn->name, uid->name, size );
- dn->name[size] = '\0'; /* make sure it's a string */
-
- /* Extract the email address from the userID string and save
- it to the email field. */
- email = strchr( uid->name, '<' );
- if( email )
- pos1 = email-uid->name + 1;
- email = strchr( uid->name, '>' );
- if( email )
- pos2 = email-uid->name + 1;
- if( pos1 && pos2 ) {
- pos2 -= pos1;
- size = pos2 < OPENPGP_NAME_SIZE? pos2 : OPENPGP_NAME_SIZE-1;
- memcpy( dn->email, uid->name+pos1, size );
- dn->email[size-1] = '\0'; /* make sure it's a string */
- }
- if( uid->is_revoked ) {
- rc = GNUTLS_E_OPENPGP_UID_REVOKED;
- goto leave;
- }
-
-leave:
- cdk_kbnode_release( knode );
- return rc;
-}
-
-/**
- * gnutls_openpgp_extract_key_name_string - Extracts the userID
- * @cert: the raw data that contains the OpenPGP public key.
- * @idx: the index of the ID to extract
- * @buf: a pointer to a structure to hold the peer's name
- * @sizeof_buf: holds the size of 'buf'
- *
- * Extracts the userID from the raw OpenPGP key.
- **/
-int
-gnutls_openpgp_extract_key_name_string( const gnutls_datum *cert,
- int idx,
- char *buf, unsigned int sizeof_buf)
-{
- CDK_KBNODE knode = NULL, ctx = NULL, p;
- CDK_PACKET *pkt = NULL;
- cdkPKT_user_id *uid = NULL;
- int pos = 0;
- size_t size = 0;
- int rc = 0;
-
- if( !cert || !buf ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- if( idx < 0 || idx > gnutls_openpgp_count_key_names( cert ) ) {
- gnutls_assert( );
- return GNUTLS_E_INTERNAL_ERROR;
- }
-
- rc = cdk_kbnode_read_from_mem( &knode, cert->data, cert->size );
- if( (rc = _gnutls_map_cdk_rc( rc )) ) {
- gnutls_assert( );
- return rc;
- }
- if( !idx )
- pkt = cdk_kbnode_find_packet( knode, CDK_PKT_USER_ID );
- else {
- pos = 0;
- while( (p = cdk_kbnode_walk( knode, &ctx, 0 )) ) {
- pkt = cdk_kbnode_get_packet( p );
- if( pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx )
- break;
- }
- }
-
- if( !pkt ) {
- rc = GNUTLS_E_INTERNAL_ERROR;
- goto leave;
- }
-
- uid = pkt->pkt.user_id;
-
- if (uid->len >= sizeof_buf) {
- gnutls_assert();
- rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
- goto leave;
- }
-
- size = uid->len < sizeof_buf? uid->len : sizeof_buf-1;
- memcpy( buf, uid->name, size);
-
- buf[size] = '\0'; /* make sure it's a string */
-
- if( uid->is_revoked ) {
- rc = GNUTLS_E_OPENPGP_UID_REVOKED;
- goto leave;
- }
-
-leave:
- cdk_kbnode_release( knode );
- return rc;
-}
-
-
-/**
- * gnutls_openpgp_extract_key_pk_algorithm - This function returns the
- * key's PublicKey algorithm
- * @cert: is an OpenPGP key
- * @bits: if bits is non null it will hold the size of the parameters' in bits
- *
- * This function will return the public key algorithm of an OpenPGP
- * certificate.
- *
- * If bits is non null, it should have enough size to hold the parameters
- * size in bits. For RSA the bits returned is the modulus.
- * For DSA the bits returned are of the public exponent.
- *
- * Returns a member of the GNUTLS_PKAlgorithm enumeration on success,
- * or a negative value on error.
- *
- **/
-int
-gnutls_openpgp_extract_key_pk_algorithm( const gnutls_datum *cert, int *r_bits)
-{
- CDK_PACKET *pkt;
- int algo = 0;
-
- if( !cert )
- return GNUTLS_E_INVALID_REQUEST;
-
- pkt = search_packet( cert, CDK_PKT_PUBLIC_KEY );
- if( pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY ) {
- if( r_bits )
- *r_bits = cdk_pk_get_nbits( pkt->pkt.public_key );
- algo = pkt->pkt.public_key->pubkey_algo;
- if( is_RSA( algo ) )
- algo = GNUTLS_PK_RSA;
- else if( is_DSA( algo ) )
- algo = GNUTLS_PK_DSA;
- else
- algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
- }
- search_packet( NULL, 0 );
- return algo;
-}
-
-
-/**
- * gnutls_openpgp_extract_key_version - Extracts the version of the key.
- * @cert: the raw data that contains the OpenPGP public key.
- *
- * Extract the version of the OpenPGP key.
- **/
-int
-gnutls_openpgp_extract_key_version( const gnutls_datum *cert )
-{
- CDK_PACKET *pkt;
- int version = 0;
-
- if( !cert )
- return -1;
-
- pkt = search_packet( cert, CDK_PKT_PUBLIC_KEY );
- if( pkt )
- version = pkt->pkt.public_key->version;
- search_packet( NULL, 0 );
-
- return version;
-}
-
-
-/**
- * gnutls_openpgp_extract_key_creation_time - Extract the timestamp
- * @cert: the raw data that contains the OpenPGP public key.
- *
- * Returns the timestamp when the OpenPGP key was created.
- **/
-time_t
-gnutls_openpgp_extract_key_creation_time( const gnutls_datum *cert )
-{
- CDK_PACKET *pkt;
- time_t timestamp = 0;
-
- if( !cert )
- return (time_t)-1;
-
- pkt = search_packet( cert, CDK_PKT_PUBLIC_KEY );
- if( pkt )
- timestamp = pkt->pkt.public_key->timestamp;
- search_packet( NULL, 0 );
-
- return timestamp;
-}
-
-
-/**
- * gnutls_openpgp_extract_key_expiration_time - Extract the expire date
- * @cert: the raw data that contains the OpenPGP public key.
- *
- * Returns the time when the OpenPGP key expires. A value of '0' means
- * that the key doesn't expire at all.
- **/
-time_t
-gnutls_openpgp_extract_key_expiration_time( const gnutls_datum *cert )
-{
- CDK_PACKET *pkt;
- time_t expiredate = 0;
-
- if( !cert )
- return (time_t)-1;
-
- pkt = search_packet( cert, CDK_PKT_PUBLIC_KEY );
- if( pkt )
- expiredate = pkt->pkt.public_key->expiredate;
- search_packet( NULL, 0 );
-
- return expiredate;
-}
-
-
-int
-_gnutls_openpgp_get_key_trust( const char *trustdb,
- const gnutls_datum *key,
- int *r_trustval )
-{
- CDK_KBNODE knode = NULL;
- CDK_STREAM inp;
- CDK_PACKET *pkt;
- cdkPKT_public_key *pk = NULL;
- int flags = 0, ot = 0;
- int rc = 0;
-
- if( !trustdb || !key || !r_trustval ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- *r_trustval = 0;
-
- rc = cdk_kbnode_read_from_mem( &knode, key->data, key->size );
- if( (rc = _gnutls_map_cdk_rc( rc )) )
- return rc;
-
- pkt = cdk_kbnode_find_packet( knode, CDK_PKT_PUBLIC_KEY );
- if( !pkt ) {
- rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
- goto leave;
- }
- pk = pkt->pkt.public_key;
-
- rc = cdk_stream_open( trustdb, &inp );
- if( rc ) {
- rc = _gnutls_map_cdk_rc( rc );
- goto leave;
- }
-
- rc = cdk_trustdb_get_ownertrust( inp, pk, &ot, &flags );
- cdk_stream_close( inp );
- if ( rc ) { /* no ownertrust record was found */
- rc = 0;
- *r_trustval = 0;
- goto leave;
- }
-
- if( flags & CDK_TFLAG_DISABLED ) {
- *r_trustval |= GNUTLS_CERT_NOT_TRUSTED;
- *r_trustval |= GNUTLS_CERT_INVALID;
- goto leave;
- }
-
- if( flags & CDK_TFLAG_REVOKED ) {
- *r_trustval |= GNUTLS_CERT_NOT_TRUSTED;
- *r_trustval |= GNUTLS_CERT_REVOKED;
- }
-
- switch( ot ) {
- case CDK_TRUST_NEVER:
- *r_trustval |= GNUTLS_CERT_NOT_TRUSTED;
- break;
- case CDK_TRUST_UNKNOWN:
- case CDK_TRUST_UNDEFINED:
- case CDK_TRUST_MARGINAL:
- case CDK_TRUST_FULLY:
- case CDK_TRUST_ULTIMATE:
- *r_trustval |= 1; /* means okay */
- rc = 0;
- break;
- }
-
-leave:
- if( rc )
- *r_trustval |= GNUTLS_CERT_NOT_TRUSTED;
- cdk_kbnode_release( knode );
- return rc;
-}
-
-
-/**
- * gnutls_openpgp_verify_key - Verify all signatures on the key
- * @cert_list: the structure that holds the certificates.
- * @cert_list_lenght: the items in the cert_list.
- *
- * Verify all signatures in the certificate list. When the key
- * is not available, the signature is skipped.
- *
- * When the trustdb parameter is used, the function checks the
- * ownertrust of the key before the signatures are checked. It
- * is possible that the key was disabled or the owner is not trusted
- * at all. Then we don't check the signatures because it makes no sense.
- *
- * The return value is one of the CertificateStatus entries.
- *
- * NOTE: this function does not verify using any "web of trust". You
- * may use GnuPG for that purpose, or any other external PGP application.
- **/
-int
-gnutls_openpgp_verify_key( const char *trustdb,
- const gnutls_datum* keyring,
- const gnutls_datum* cert_list,
- int cert_list_length )
-{
- CDK_KBNODE knode = NULL;
- CDK_KEYDB_HD hd = NULL;
- keybox_blob *blob = NULL;
- int rc = 0;
- int status = 0;
-
- if( !cert_list || cert_list_length != 1 || !keyring ) {
- gnutls_assert();
- return GNUTLS_E_NO_CERTIFICATE_FOUND;
- }
-
- if( !keyring->size && !trustdb ) {
- gnutls_assert( );
- return GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED;
- }
-
- blob = kbx_read_blob( keyring, 0 );
- if( !blob ) {
- gnutls_assert();
- return GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED;
- }
- hd = kbx_to_keydb( blob );
- if( !hd ) {
- rc = GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED;
- goto leave;
- }
-
- if( trustdb ) {
- int ktrust;
- rc = _gnutls_openpgp_get_key_trust( trustdb, cert_list, &ktrust );
- if( rc || !ktrust )
- goto leave;
- }
-
- rc = cdk_kbnode_read_from_mem( &knode, cert_list->data, cert_list->size );
- if( (rc = _gnutls_map_cdk_rc( rc )) ) {
- goto leave;
- return GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED;
- }
-
- rc = cdk_key_check_sigs( knode, hd, &status );
- if( rc == CDK_Error_No_Key )
- rc = 0; /* fixme */
-
- switch( status ) {
- case CDK_KEY_INVALID:
- rc = GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED;
- break;
-
- case CDK_KEY_REVOKED:
- rc = GNUTLS_CERT_REVOKED | GNUTLS_CERT_NOT_TRUSTED;
- break;
- }
-
-leave:
- kbx_blob_release( blob );
- cdk_free( hd );
- cdk_kbnode_release( knode );
- if( rc ) {
- gnutls_assert();
- }
- return rc;
-}
-
-
-/**
- * gnutls_openpgp_fingerprint - Gets the fingerprint
- * @cert: the raw data that contains the OpenPGP public key.
- * @fpr: the buffer to save the fingerprint.
- * @fprlen: the integer to save the length of the fingerprint.
- *
- * Returns the fingerprint of the OpenPGP key. Depence on the algorithm,
- * the fingerprint can be 16 or 20 bytes.
- **/
-int
-gnutls_openpgp_fingerprint( const gnutls_datum *cert,
- unsigned char *fpr, size_t *fprlen )
-{
- CDK_PACKET *pkt;
- cdkPKT_public_key *pk = NULL;
-
- if( !cert || !fpr || !fprlen ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- *fprlen = 0;
-
- pkt = search_packet( cert, CDK_PKT_PUBLIC_KEY );
- if( !pkt )
- return GNUTLS_E_OPENPGP_GETKEY_FAILED;
-
- pk = pkt->pkt.public_key;
- *fprlen = 20;
- if ( is_RSA(pk->pubkey_algo) && pk->version < 4 )
- *fprlen = 16;
- cdk_pk_get_fingerprint( pk, fpr );
- search_packet( NULL, 0 );
-
- return 0;
-}
-
-
-/**
- * gnutls_openpgp_extract_key_id - Gets the keyID
- * @cert: the raw data that contains the OpenPGP public key.
- * @keyid: the buffer to save the keyid.
- *
- * Returns the 64-bit keyID of the OpenPGP key.
- **/
-int
-gnutls_openpgp_extract_key_id( const gnutls_datum *cert,
- unsigned char keyid[8] )
-{
- CDK_PACKET *pkt;
- cdkPKT_public_key *pk = NULL;
- unsigned long kid[2];
-
- if( !cert || !keyid ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- pkt = search_packet( cert, CDK_PKT_PUBLIC_KEY );
- if( !pkt )
- return GNUTLS_E_OPENPGP_GETKEY_FAILED;
-
- pk = pkt->pkt.public_key;
- cdk_pk_get_keyid( pk, kid );
- keyid[0] = kid[0] >> 24;
- keyid[1] = kid[0] >> 16;
- keyid[2] = kid[0] >> 8;
- keyid[3] = kid[0];
- keyid[4] = kid[1] >> 24;
- keyid[5] = kid[1] >> 16;
- keyid[6] = kid[1] >> 8;
- keyid[7] = kid[1];
- search_packet( NULL, 0 );
-
- return 0;
-}
-
-
-/*-
- * gnutls_openpgp_add_keyring_file - Adds a keyring file for OpenPGP
- * @keyring: data buffer to store the file.
- * @name: filename of the keyring.
- *
- * The function is used to set keyrings that will be used internally
- * by various OpenCDK functions. For example to find a key when it
- * is needed for an operations.
- -*/
-int
-gnutls_openpgp_add_keyring_file(gnutls_datum *keyring, const char *name)
-{
- CDK_STREAM inp = NULL;
- uint8 *blob;
- size_t nbytes;
- int enc = 0;
- int rc = 0;
-
- if( !keyring || !name ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- rc = cdk_stream_open( name, &inp );
- if( rc )
- return _gnutls_map_cdk_rc( rc );
- enc = cdk_armor_filter_use( inp );
- cdk_stream_close( inp );
-
- blob = kbx_data_to_keyring( KBX_BLOB_FILE, enc, name,
- strlen( name ), &nbytes);
- if( blob && nbytes ) {
- if ( datum_append( keyring, blob, nbytes ) < 0 ) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- gnutls_free( blob );
- }
- return 0;
-}
-
-
-/*-
- * gnutls_openpgp_add_keyring_mem - Adds keyring data for OpenPGP
- * @keyring: data buffer to store the file.
- * @data: the binary data of the keyring.
- * @len: the size of the binary buffer.
- *
- * Same as gnutls_openpgp_add_keyring_mem but now we store the
- * data instead of the filename.
- -*/
-int
-gnutls_openpgp_add_keyring_mem(gnutls_datum *keyring,
- const opaque *data, size_t len)
-{
- uint8 *blob;
- size_t nbytes = 0;
-
- if( !keyring || !data || !len ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- blob = kbx_data_to_keyring( KBX_BLOB_DATA, 0, data, len, &nbytes );
- if( blob && nbytes ) {
- if ( datum_append( keyring, blob, nbytes ) < 0 ) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- gnutls_free( blob );
- }
-
- return 0;
-}
-
-
-/**
- * gnutls_certificate_set_openpgp_keyring_file - Adds a keyring file for OpenPGP * @c: A certificate credentials structure
- * @file: filename of the keyring.
- *
- * The function is used to set keyrings that will be used internally
- * by various OpenPGP functions. For example to find a key when it
- * is needed for an operations. The keyring will also be used at the
- * verification functions.
- *
- **/
-int
-gnutls_certificate_set_openpgp_keyring_file( gnutls_certificate_credentials c,
- const char *file )
-{
- struct stat statbuf;
-
- if( !c || !file ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- if( stat( file, &statbuf ) )
- return GNUTLS_E_FILE_ERROR;
-
- return gnutls_openpgp_add_keyring_file( &c->keyring, file );
-}
-
-
-int
-gnutls_certificate_set_openpgp_keyring_mem( gnutls_certificate_credentials c,
- const opaque *data, size_t dlen )
-{
- CDK_STREAM inp;
- size_t count;
- uint8 *buf;
- int rc = 0;
-
- if( !c || !data || !dlen ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- inp = cdk_stream_tmp_from_mem( data, dlen );
- if( !inp )
- return GNUTLS_E_FILE_ERROR;
-
- /* Maybe it's a little confusing that we check the output..
- but it's possible, that the data we want to add, is armored
- and we only want to store plaintext keyring data. */
- if( cdk_armor_filter_use( inp ) )
- cdk_stream_set_armor_flag( inp, 0 );
-
- /* fixme: this is possible the armored length. */
- count = cdk_stream_get_length( inp );
- buf = gnutls_malloc( count + 1 );
- if( !buf ) {
- gnutls_assert();
- cdk_stream_close( inp );
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- count = cdk_stream_read( inp, buf, count );
- buf[count] = '\0';
- rc = gnutls_openpgp_add_keyring_mem( &c->keyring, buf, count );
- cdk_stream_close( inp );
-
- return rc;
-}
-
-/*-
- * _gnutls_openpgp_request_key - Receives a key from a database, key server etc
- * @ret - a pointer to gnutls_datum structure.
- * @cred - a gnutls_certificate_credentials structure.
- * @key_fingerprint - The keyFingerprint
- * @key_fingerprint_size - the size of the fingerprint
- *
- * Retrieves a key from a local database, keyring, or a key server. The
- * return value is locally allocated.
- *
- -*/
-int
-_gnutls_openpgp_request_key( gnutls_session session, gnutls_datum* ret,
- const gnutls_certificate_credentials cred,
- opaque* key_fpr,
- int key_fpr_size)
-{
- int rc = 0;
-
- if( !ret || !cred || !key_fpr ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- if( key_fpr_size != 16 && key_fpr_size != 20 )
- return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */
-
- rc = gnutls_openpgp_get_key( ret, &cred->keyring, KEY_ATTR_FPR, key_fpr );
- if( rc >= 0 ) /* key was found */
- return rc;
- else rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
-
- /* If the callback function was set, then try this one.
- */
- if( session->internals.openpgp_recv_key_func != NULL ) {
- rc = session->internals.openpgp_recv_key_func( session,
- key_fpr,
- key_fpr_size,
- ret);
- if( rc < 0 ) {
- gnutls_assert();
- return GNUTLS_E_OPENPGP_GETKEY_FAILED;
- }
- }
-
- return rc;
-}
-
-
-/**
- * gnutls_certificate_set_openpgp_keyserver - Used to set an OpenPGP key server
- * @res: the destination context to save the data.
- * @server: is the key server address
- * @port: is the key server port to connect to
- *
- * This funtion will set a key server for use with openpgp keys. This
- * key server will only be used if the peer sends a key fingerprint instead
- * of a key in the handshake. Using a key server may delay the handshake
- * process.
- *
- **/
-int
-gnutls_certificate_set_openpgp_keyserver(gnutls_certificate_credentials res,
- char* keyserver,
- int port)
-{
- if( !res || !keyserver ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- if( !port )
- port = 11371;
-
- gnutls_free( res->pgp_key_server);
- res->pgp_key_server = gnutls_strdup( keyserver );
- if( !res->pgp_key_server )
- return GNUTLS_E_MEMORY_ERROR;
- res->pgp_key_server_port = port;
-
- return 0;
-}
-
-
-static int
-xml_add_tag( gnutls_string *xmlkey, const char *tag, const char *val )
-{
- if( !xmlkey || !tag || !val ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- _gnutls_string_append_str( xmlkey, " <" );
- _gnutls_string_append_str( xmlkey, tag );
- _gnutls_string_append_str( xmlkey, ">" );
- _gnutls_string_append_str( xmlkey, val );
- _gnutls_string_append_str( xmlkey, "</" );
- _gnutls_string_append_str( xmlkey, tag );
- _gnutls_string_append_str( xmlkey, ">\n" );
-
- return 0;
-}
-
-
-static int
-xml_add_mpi2( gnutls_string *xmlkey, const uint8 *data, size_t count,
- const char *tag )
-{
- char *p = NULL;
- size_t i;
- int rc = 0;
-
- if( !xmlkey || !data || !tag ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- p = gnutls_calloc( 1, 2 * ( count + 3 ) );
- if( !p ) {
- gnutls_assert( );
- return GNUTLS_E_MEMORY_ERROR;
- }
- for( i = 0; i < count; i++ )
- sprintf( p + 2 * i, "%02X", data[i] );
- p[2 * count] = '\0';
-
- rc = xml_add_tag( xmlkey, tag, p );
- gnutls_free( p );
-
- return rc;
-}
-
-
-static int
-xml_add_mpi( gnutls_string *xmlkey, cdkPKT_public_key *pk, int idx,
- const char *tag )
-{
- uint8 buf[4096];
- size_t nbytes;
-
- nbytes = sizeof buf-1;
- cdk_pk_get_mpi( pk, idx, buf, &nbytes, NULL );
- return xml_add_mpi2( xmlkey, buf, nbytes, tag );
-}
-
-
-
-static int
-xml_add_key_mpi( gnutls_string *xmlkey, cdkPKT_public_key *pk )
-{
- const char *s = " <KEY ENCODING=\"HEX\"/>\n";
- int rc = 0;
-
- if( !xmlkey || !pk ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- _gnutls_string_append_str( xmlkey, s );
-
- if( is_RSA( pk->pubkey_algo ) ) {
- rc = xml_add_mpi( xmlkey, pk, 0, "RSA-N" );
- if( !rc )
- rc = xml_add_mpi( xmlkey, pk, 1, "RSA-E" );
- }
- else if( is_DSA( pk->pubkey_algo ) ) {
- rc = xml_add_mpi( xmlkey, pk, 0, "DSA-P" );
- if( !rc )
- rc = xml_add_mpi( xmlkey, pk, 1, "DSA-Q" );
- if( !rc )
- rc = xml_add_mpi( xmlkey, pk, 2, "DSA-G" );
- if( !rc )
- rc = xml_add_mpi( xmlkey, pk, 3, "DSA-Y" );
- }
- else if( is_ELG( pk->pubkey_algo ) ) {
- rc = xml_add_mpi( xmlkey, pk, 0, "ELG-P" );
- if( !rc )
- rc = xml_add_mpi( xmlkey, pk, 1, "ELG-G" );
- if( !rc )
- rc = xml_add_mpi( xmlkey, pk, 2, "ELG-Y" );
- }
- else
- return GNUTLS_E_UNWANTED_ALGORITHM;
-
- return 0;
-}
-
-
-static int
-xml_add_key( gnutls_string *xmlkey, int ext, cdkPKT_public_key *pk, int sub )
-{
- const char *algo, *s;
- char keyid[16], fpr[41], tmp[32];
- uint8 fingerpr[20];
- unsigned long kid[2];
- int i = 0, rc = 0;
-
- if( !xmlkey || !pk ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- s = sub? " <SUBKEY>\n" : " <MAINKEY>\n";
- _gnutls_string_append_str( xmlkey, s );
-
- cdk_pk_get_keyid( pk, kid );
- snprintf( keyid, 16, "%08lX%08lX", kid[0], kid[1] );
- rc = xml_add_tag( xmlkey, "KEYID", keyid );
- if( rc )
- return rc;
-
- cdk_pk_get_fingerprint( pk, fingerpr );
- for ( i = 0; i < 20; i++ )
- sprintf( fpr + 2 * i, "%02X", fingerpr[i] );
- fpr[40] = '\0';
- rc = xml_add_tag( xmlkey, "FINGERPRINT", fpr );
- if( rc )
- return rc;
-
- if( is_DSA( pk->pubkey_algo ) )
- algo = "DSA";
- else if( is_RSA( pk->pubkey_algo ) )
- algo = "RSA";
- else if( is_ELG( pk->pubkey_algo ) )
- algo = "ELG";
- else algo = "???";
- rc = xml_add_tag( xmlkey, "PKALGO", algo );
- if( rc )
- return rc;
-
- sprintf( tmp, "%d", cdk_pk_get_nbits( pk ) );
- rc = xml_add_tag( xmlkey, "KEYLEN", tmp );
- if( rc )
- return rc;
-
- sprintf( tmp, "%lu", pk->timestamp );
- rc = xml_add_tag( xmlkey, "CREATED", tmp );
- if( rc )
- return rc;
-
- if( pk->expiredate > 0 ) {
- sprintf( tmp, "%lu", (unsigned long)pk->expiredate );
- rc = xml_add_tag( xmlkey, "EXPIREDATE", tmp );
- if( rc )
- return rc;
- }
-
- sprintf( tmp, "%d", pk->is_revoked );
- rc = xml_add_tag( xmlkey, "REVOKED", tmp );
- if( rc )
- return rc;
-
- if( ext ) {
- rc = xml_add_key_mpi( xmlkey, pk );
- if( rc )
- return rc;
- }
-
- s = sub? " </SUBKEY>\n" : " </MAINKEY>\n";
- _gnutls_string_append_str( xmlkey, s );
-
- return 0;
-}
-
-
-static int
-xml_add_userid( gnutls_string *xmlkey, int ext,
- gnutls_openpgp_name *dn, cdkPKT_user_id *id )
-{
- const char *s;
- char *p, *name, tmp[32];
- int rc = 0;
-
- if( !xmlkey || !dn || !id ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- s = " <USERID>\n";
- _gnutls_string_append_str( xmlkey, s );
-
- p = strchr( dn->name, '<' );
- if ( p ) {
- int len = (p - dn->name - 1);
- name = gnutls_calloc( 1, len );
- if( !name ) {
- gnutls_assert( );
- return GNUTLS_E_MEMORY_ERROR;
- }
- memcpy( name, dn->name, len );
- rc = xml_add_tag( xmlkey, "NAME", name );
- gnutls_free( name );
- if( rc )
- return rc;
- }
- else {
- rc = xml_add_tag( xmlkey, "NAME", dn->name );
- if( rc )
- return rc;
- }
-
- rc = xml_add_tag( xmlkey, "EMAIL", dn->email );
- if( rc )
- return rc;
-
- if ( ext ) {
- sprintf( tmp, "%d", id->is_primary );
- rc = xml_add_tag( xmlkey, "PRIMARY", tmp );
- if( rc )
- return rc;
- sprintf( tmp, "%d", id->is_revoked );
- rc = xml_add_tag( xmlkey, "REVOKED", tmp );
- if( rc )
- return rc;
- }
-
- s = " </USERID>\n";
- _gnutls_string_append_str( xmlkey, s );
-
- return 0;
-}
-
-
-static int
-xml_add_sig( gnutls_string *xmlkey, int ext, cdkPKT_signature *sig )
-{
- const char *algo, *s;
- char tmp[32], keyid[16];
- unsigned long kid[2];
- int rc = 0;
-
- if( !xmlkey || !sig ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- s = " <SIGNATURE>\n";
- _gnutls_string_append_str( xmlkey, s );
-
- sprintf( tmp, "%d", sig->version );
- rc = xml_add_tag( xmlkey, "VERSION", tmp );
- if( rc )
- return rc;
-
- if( ext ) {
- sprintf( tmp, "%d", sig->sig_class );
- rc = xml_add_tag( xmlkey, "SIGCLASS", tmp );
- if( rc )
- return rc;
- }
-
- sprintf( tmp, "%d", sig->flags.expired );
- rc = xml_add_tag( xmlkey, "EXPIRED", tmp );
- if( rc )
- return rc;
-
- if ( ext ) {
- switch( sig->pubkey_algo ) {
- case GCRY_PK_DSA : algo = "DSA"; break;
- case GCRY_PK_ELG :
- case GCRY_PK_ELG_E: algo = "ELG"; break;
- case GCRY_PK_RSA :
- case GCRY_PK_RSA_E:
- case GCRY_PK_RSA_S: algo = "RSA"; break;
- default : algo = "???"; /* unknown algorithm */
- }
- rc = xml_add_tag( xmlkey, "PKALGO", algo );
- if( rc )
- return rc;
-
- switch( sig->digest_algo ) {
- case GCRY_MD_SHA1 : algo = "SHA1"; break;
- case GCRY_MD_RMD160: algo = "RMD160"; break;
- case GCRY_MD_MD5 : algo = "MD5"; break;
- default : algo = "???";
- }
- rc = xml_add_tag( xmlkey, "MDALGO", algo );
- if( rc )
- return rc;
- }
-
- sprintf( tmp, "%lu", sig->timestamp );
- rc = xml_add_tag( xmlkey, "CREATED", tmp );
- if( rc )
- return rc;
-
- cdk_sig_get_keyid( sig, kid );
- snprintf( keyid, 16, "%08lX%08lX", kid[0], kid[1] );
- rc = xml_add_tag( xmlkey, "KEYID", keyid );
- if( rc )
- return rc;
-
- s = " </SIGNATURE>\n";
- _gnutls_string_append_str( xmlkey, s );
-
- return 0;
-}
-
-
-/**
- * gnutls_openpgp_key_to_xml - Return a certificate as a XML fragment
- * @cert: the certificate which holds the whole OpenPGP key.
- * @xmlkey: he datum struct to store the XML result.
- * @ext: extension mode (1/0), 1 means include key signatures and key data.
- *
- * This function will return the all OpenPGP key information encapsulated as
- * a XML string.
- **/
-int
-gnutls_openpgp_key_to_xml( const gnutls_datum *cert,
- gnutls_datum *xmlkey, int ext )
-{
- CDK_KBNODE knode, node, ctx = NULL;
- CDK_PACKET *pkt;
- gnutls_openpgp_name dn;
- const char *s;
- int idx = 0, rc = 0;
- gnutls_string string_xml_key;
-
- if( !cert || !xmlkey ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- rc = cdk_kbnode_read_from_mem( &knode, cert->data, cert->size );
- if( (rc = _gnutls_map_cdk_rc( rc )) )
- return rc;
-
- _gnutls_string_init( &string_xml_key, malloc, realloc, free );
- memset( xmlkey, 0, sizeof *xmlkey );
-
- s = "<?xml version=\"1.0\"?>\n\n";
- _gnutls_string_append_str( &string_xml_key, s );
-
- s = "<gnutls:openpgp:key version=\"1.0\">\n";
- _gnutls_string_append_str( &string_xml_key, s );
-
- s = " <OPENPGPKEY>\n";
- _gnutls_string_append_str( &string_xml_key, s );
-
- idx = 1;
- while( (node = cdk_kbnode_walk( knode, &ctx, 0 )) ) {
- pkt = cdk_kbnode_get_packet( node );
- switch ( pkt->pkttype ) {
- case CDK_PKT_PUBLIC_KEY:
- rc = xml_add_key( &string_xml_key, ext, pkt->pkt.public_key, 0 );
- break;
-
- case CDK_PKT_PUBLIC_SUBKEY:
- rc = xml_add_key( &string_xml_key, ext, pkt->pkt.public_key, 1 );
- break;
-
- case CDK_PKT_USER_ID:
- gnutls_openpgp_extract_key_name( cert, idx, &dn );
- rc = xml_add_userid( &string_xml_key, ext, &dn, pkt->pkt.user_id );
- idx++;
- break;
-
- case CDK_PKT_SIGNATURE:
- rc = xml_add_sig( &string_xml_key, ext, pkt->pkt.signature );
- break;
-
- default:
- break;
- }
- }
- if( !rc ) {
- s = " </OPENPGPKEY>\n";
- _gnutls_string_append_str( &string_xml_key, s );
- }
- s = "</gnutls:openpgp:key>\n";
- _gnutls_string_append_str( &string_xml_key, s );
- _gnutls_string_append_data( &string_xml_key, "\n\0", 2 );
-
- *xmlkey = _gnutls_string2datum( &string_xml_key );
- xmlkey->size--;
-
- cdk_kbnode_release( knode );
- return rc;
-}
-
-
-/**
- * gnutls_certificate_set_openpgp_trustdb - Used to set an GnuPG trustdb
- * @res: the destination context to save the data.
- * @trustdb: is the trustdb filename
- *
- * This funtion will set a GnuPG trustdb which will be used in key
- * verification functions. Only version 3 trustdb files are supported.
- *
- **/
-int
-gnutls_certificate_set_openpgp_trustdb( gnutls_certificate_credentials res,
- char* trustdb )
-{
- if( !res || !trustdb ) {
- gnutls_assert( );
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* the old v2 format was used with 1.0.6, do we still need to check
- it now because GPG 1.0.7, 1.2.0, 1.2.1 and even 1.3.0 is out? */
-
- gnutls_free( res->pgp_trustdb);
- res->pgp_trustdb = gnutls_strdup( trustdb );
- if( res->pgp_trustdb==NULL )
- return GNUTLS_E_MEMORY_ERROR;
-
- return 0;
-}
-
-/**
- * gnutls_openpgp_set_recv_key_function - Used to set a key retrieval callback for PGP keys
- * @session: a TLS session
- * @func: the callback
- *
- * This funtion will set a key retrieval function for OpenPGP keys. This
- * callback is only useful in server side, and will be used if the peer
- * sent a key fingerprint instead of a full key.
- *
- **/
-void gnutls_openpgp_set_recv_key_function( gnutls_session session,
- gnutls_openpgp_recv_key_func func )
-{
- session->internals.openpgp_recv_key_func = func;
-}
-
-#else /*!HAVE_LIBOPENCDK*/
-int
-_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
- gnutls_datum raw_key )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-_gnutls_openpgp_cert2gnutls_cert( gnutls_cert *cert, const gnutls_datum *raw )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_certificate_set_openpgp_key_mem(gnutls_certificate_credentials res,
- gnutls_datum *cert,
- gnutls_datum *key)
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_certificate_set_openpgp_key_file( gnutls_certificate_credentials res,
- char* CERTFILE,
- char* KEYFILE )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_extract_key_name( const gnutls_datum *cert, int idx,
- gnutls_openpgp_name *dn )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_extract_key_pk_algorithm(const gnutls_datum *cert, int *r_bits)
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_extract_key_version( const gnutls_datum *cert )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-time_t
-gnutls_openpgp_extract_key_creation_time( const gnutls_datum *cert )
-{
- return (time_t)-1;
-}
-
-time_t
-gnutls_openpgp_extract_key_expiration_time( const gnutls_datum *cert )
-{
- return (time_t)-1;
-}
-
-int
-gnutls_openpgp_verify_key( const char* ign, const gnutls_datum* keyring,
- const gnutls_datum* cert_list,
- int cert_list_length )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_fingerprint(const gnutls_datum *cert, unsigned char *fpr, size_t *fprlen)
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_add_keyring_file( gnutls_datum *keyring, const char *name )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_add_keyring_mem( gnutls_datum *keyring,
- const opaque *data, size_t len )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_certificate_set_openpgp_keyring_file( gnutls_certificate_credentials c,
- const char *file )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_certificate_set_openpgp_keyring_mem( gnutls_certificate_credentials c,
- const opaque* data,
- size_t dlen)
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-_gnutls_openpgp_request_key( gnutls_session session, gnutls_datum* ret,
- const gnutls_certificate_credentials cred,
- opaque* key_fpr,
- int key_fpr_size )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_certificate_set_openpgp_keyserver( gnutls_certificate_credentials res,
- char* keyserver,
- int port )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_certificate_set_openpgp_trustdb( gnutls_certificate_credentials res,
- char* trustdb )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_key_to_xml( const gnutls_datum *cert,
- gnutls_datum *xmlkey, int ext )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_extract_key_id( const gnutls_datum *cert,
- unsigned char keyid[8] )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-void gnutls_openpgp_set_recv_key_function( gnutls_session session,
- gnutls_openpgp_recv_key_func func )
-{
-
-}
-
-int
-gnutls_openpgp_extract_key_name_string( const gnutls_datum *cert,
- int idx,
- char *buf, unsigned int sizeof_buf)
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int
-gnutls_openpgp_get_key( gnutls_datum *key, const gnutls_datum *keyring,
- key_attr_t by, opaque *pattern )
-{
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-#endif /* HAVE_LIBOPENCDK */
-