diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2004-05-13 06:39:45 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2004-05-13 06:39:45 +0000 |
commit | b4eeab22afb5744b082248ed263281f7f603f323 (patch) | |
tree | 4e04a1afb086ed133bd207931786800fcf8a3095 /libextra/opencdk/new-packet.c | |
parent | cf3b1fbffaa20c40d645ba1192549cb1bf59d0e7 (diff) | |
download | gnutls-b4eeab22afb5744b082248ed263281f7f603f323.tar.gz |
Opencdk library is being included if not found.
Diffstat (limited to 'libextra/opencdk/new-packet.c')
-rw-r--r-- | libextra/opencdk/new-packet.c | 775 |
1 files changed, 775 insertions, 0 deletions
diff --git a/libextra/opencdk/new-packet.c b/libextra/opencdk/new-packet.c new file mode 100644 index 0000000000..6251fbd2f6 --- /dev/null +++ b/libextra/opencdk/new-packet.c @@ -0,0 +1,775 @@ +/* -*- Mode: C; c-file-style: "bsd" -*- + * new-packet.c - General packet handling (freeing, copying, ...) + * Copyright (C) 2001, 2002, 2003 Timo Schulz + * + * This file is part of OpenCDK. + * + * OpenCDK 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. + * + * OpenCDK 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 OpenCDK; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <string.h> +#include <stdio.h> +#include <assert.h> + +#include "opencdk.h" +#include "main.h" +#include "packet.h" + + +void +_cdk_free_mpibuf( size_t n, gcry_mpi_t * array ) +{ + while( n-- ) { + gcry_mpi_release( array[n] ); + array[n] = NULL; + } +} + + +cdk_error_t +cdk_pkt_new( cdk_packet_t* r_pkt ) +{ + cdk_packet_t pkt; + + if( !r_pkt ) + return CDK_Inv_Value; + pkt = cdk_calloc( 1, sizeof *pkt ); + if( !pkt ) + return CDK_Out_Of_Core; + *r_pkt = pkt; + return 0; +} + + +void +cdk_pkt_init( cdk_packet_t pkt ) +{ + if( pkt ) + memset( pkt, 0, sizeof * pkt ); +} + + +static void +free_symkey_enc (cdk_pkt_symkey_enc_t enc) +{ + if (enc) { + cdk_free (enc->s2k); + cdk_free (enc); + } +} + + +static void +free_pubkey_enc (cdk_pkt_pubkey_enc_t enc) +{ + int nenc; + if (enc) { + nenc = cdk_pk_get_nenc (enc->pubkey_algo); + while (enc->mpi && nenc--) { + cdk_free (enc->mpi[nenc]); + enc->mpi[nenc] = NULL; + } + cdk_free (enc); + } +} + + +static void +free_literal (cdk_pkt_literal_t pt) +{ + if (pt) + cdk_free (pt); +} + + +void +_cdk_free_userid (cdk_pkt_userid_t uid) +{ + if (uid) { + cdk_free (uid->prefs); + uid->prefs = NULL; + cdk_free (uid->attrib_img); + uid->attrib_img = NULL; + cdk_free (uid); + } +} + + +void +_cdk_free_signature (cdk_pkt_signature_t sig) +{ + int nsig; + cdk_desig_revoker_t r; + + if (sig) { + nsig = cdk_pk_get_nsig (sig->pubkey_algo); + while (sig->mpi && nsig--) { + cdk_free (sig->mpi[nsig]); + sig->mpi[nsig] = NULL; + } + cdk_subpkt_free (sig->hashed); + sig->hashed = NULL; + cdk_subpkt_free (sig->unhashed); + sig->unhashed = NULL; + while( sig->revkeys ) { + r = sig->revkeys->next; + cdk_free( sig->revkeys ); + sig->revkeys = r; + } + cdk_free (sig); + } +} + + +void +_cdk_free_pubkey (cdk_pkt_pubkey_t pk) +{ + int npkey; + if (pk) { + npkey = cdk_pk_get_npkey (pk->pubkey_algo); + _cdk_free_userid (pk->uid); + pk->uid = NULL; + cdk_free (pk->prefs); + pk->prefs = NULL; + while (pk->mpi && npkey--) { + cdk_free (pk->mpi[npkey]); + pk->mpi[npkey] = NULL; + } + cdk_free (pk); + } +} + + +void +_cdk_free_seckey (cdk_pkt_seckey_t sk) +{ + int nskey; + + if (sk) { + nskey = cdk_pk_get_nskey (sk->pubkey_algo); + while (nskey--) { + if (sk->mpi[nskey]) { + wipemem (sk->mpi[nskey], sk->mpi[nskey]->bytes); + cdk_free (sk->mpi[nskey]); + sk->mpi[nskey] = NULL; + } + } + cdk_free (sk->encdata); + sk->encdata = NULL; + _cdk_free_pubkey (sk->pk); + sk->pk = NULL; + cdk_free (sk->protect.s2k); + sk->protect.s2k = NULL; + cdk_free (sk); + } +} + + +static void +free_encrypted (cdk_pkt_encrypted_t enc) +{ + if (enc) { + cdk_stream_close (enc->buf); + enc->buf = NULL; + cdk_free (enc); + } +} + + +void +cdk_pkt_free (cdk_packet_t pkt) +{ + if (!pkt) + return; + + switch (pkt->pkttype) { + case CDK_PKT_ATTRIBUTE : + case CDK_PKT_USER_ID : _cdk_free_userid (pkt->pkt.user_id); break; + case CDK_PKT_PUBLIC_KEY : + case CDK_PKT_PUBLIC_SUBKEY: _cdk_free_pubkey (pkt->pkt.public_key); break; + case CDK_PKT_SECRET_KEY : + case CDK_PKT_SECRET_SUBKEY: _cdk_free_seckey (pkt->pkt.secret_key); break; + case CDK_PKT_SIGNATURE : _cdk_free_signature (pkt->pkt.signature);break; + case CDK_PKT_PUBKEY_ENC : free_pubkey_enc (pkt->pkt.pubkey_enc); break; + case CDK_PKT_SYMKEY_ENC : free_symkey_enc (pkt->pkt.symkey_enc); break; + case CDK_PKT_MDC : cdk_free (pkt->pkt.mdc); break; + case CDK_PKT_ENCRYPTED : + case CDK_PKT_ENCRYPTED_MDC: free_encrypted (pkt->pkt.encrypted); break; + case CDK_PKT_ONEPASS_SIG : cdk_free (pkt->pkt.onepass_sig); break; + case CDK_PKT_LITERAL : free_literal (pkt->pkt.literal); break; + case CDK_PKT_COMPRESSED : cdk_free (pkt->pkt.compressed); break; + default : break; + } +} + + +void +cdk_pkt_release (cdk_packet_t pkt) +{ + if (pkt) { + cdk_pkt_free (pkt); + cdk_free (pkt); + } +} + + +cdk_error_t +cdk_pkt_alloc( cdk_packet_t* r_pkt, int pkttype ) +{ + cdk_packet_t pkt; + int rc = 0; + + if( !r_pkt ) + return CDK_Inv_Value; + + rc = cdk_pkt_new( &pkt ); + if( rc ) + return rc; + + switch (pkttype) { + case CDK_PKT_USER_ID: + pkt->pkt.user_id = cdk_calloc (1, sizeof pkt->pkt.user_id); + if (!pkt->pkt.user_id) + return CDK_Out_Of_Core; + break; + + case CDK_PKT_PUBLIC_KEY: + case CDK_PKT_PUBLIC_SUBKEY: + pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); + if (!pkt->pkt.public_key) + return CDK_Out_Of_Core; + break; + + case CDK_PKT_SECRET_KEY: + case CDK_PKT_SECRET_SUBKEY: + pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key); + pkt->pkt.secret_key->pk = + cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk); + if (!pkt->pkt.secret_key || !pkt->pkt.secret_key->pk) + return CDK_Out_Of_Core; + break; + + case CDK_PKT_SIGNATURE: + pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature); + if (!pkt->pkt.signature) + return CDK_Out_Of_Core; + break; + + case CDK_PKT_PUBKEY_ENC: + pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc); + if (!pkt->pkt.pubkey_enc) + return CDK_Out_Of_Core; + break; + + case CDK_PKT_MDC: + pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc); + if (!pkt->pkt.mdc) + return CDK_Out_Of_Core; + break; + + case CDK_PKT_ENCRYPTED_MDC: + case CDK_PKT_ENCRYPTED: + pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc); + if (!pkt->pkt.symkey_enc) + return CDK_Out_Of_Core; + break; + + case CDK_PKT_LITERAL: + pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal); + if (!pkt->pkt.literal) + return CDK_Out_Of_Core; + break; + } + pkt->pkttype = pkttype; + *r_pkt = pkt; + return 0; +} + + +byte * +cdk_userid_pref_get_array( cdk_pkt_userid_t id, int type, size_t *ret_len ) +{ + cdk_prefitem_t prefs; + byte * p; + int i = 0, j = 0; + + if( !id || !id->prefs || !ret_len ) + return NULL; + + prefs = id->prefs; + while( prefs[i].type ) { + if( prefs[i].type == type ) + j++; + i++; + } + if( !j ) + return 0; + p = cdk_calloc( 1, j + 1 ); + *ret_len = j; + i = j = 0; + while( prefs[i].type ) { + if( prefs[i].type == type ) + p[j++] = prefs[i].value; + i++; + } + p[j] = 0; + return p; +} + + +cdk_prefitem_t +_cdk_copy_prefs( const cdk_prefitem_t prefs ) +{ + size_t n = 0; + struct cdk_prefitem_s *new_prefs; + + if (!prefs) + return NULL; + + for (n = 0; prefs[n].type; n++) + ; + new_prefs = cdk_calloc (1, sizeof *new_prefs * (n + 1)); + if (!new_prefs) + return NULL; + for (n = 0; prefs[n].type; n++) { + new_prefs[n].type = prefs[n].type; + new_prefs[n].value = prefs[n].value; + } + new_prefs[n].type = CDK_PREFTYPE_NONE; + new_prefs[n].value = 0; + + return new_prefs; +} + + +cdk_error_t +_cdk_copy_userid (cdk_pkt_userid_t* dst, cdk_pkt_userid_t src) +{ + cdk_pkt_userid_t u; + + if (!dst || !src) + return CDK_Inv_Value; + + u = cdk_calloc (1, sizeof *u + strlen (src->name) + 1); + if (!u) + return CDK_Out_Of_Core; + memcpy (u, src, sizeof *u); + memcpy (u->name, src->name, strlen (src->name)); + u->prefs = _cdk_copy_prefs (src->prefs); + *dst = u; + + return 0; +} + + +cdk_error_t +_cdk_copy_pubkey (cdk_pkt_pubkey_t* dst, cdk_pkt_pubkey_t src) +{ + cdk_pkt_pubkey_t k; + int i; + + if (!dst || !src) + return CDK_Inv_Value; + + k = cdk_calloc (1, sizeof *k); + if (!k) + return CDK_Out_Of_Core; + memcpy (k, src, sizeof *k); + if (src->uid) + _cdk_copy_userid (&k->uid, src->uid); + if (src->prefs) + k->prefs = _cdk_copy_prefs (src->prefs); + for (i = 0; i < cdk_pk_get_npkey (src->pubkey_algo); i++) { + k->mpi[i] = cdk_calloc (1, sizeof **k->mpi + src->mpi[i]->bytes + 2); + if (!k->mpi[i]) + return CDK_Out_Of_Core; + k->mpi[i]->bits = src->mpi[i]->bits; + k->mpi[i]->bytes = src->mpi[i]->bytes; + /* copy 2 extra bytes (prefix) */ + memcpy (k->mpi[i]->data, src->mpi[i]->data, src->mpi[i]->bytes + 2); + } + *dst = k; + + return 0; +} + + +cdk_error_t +_cdk_copy_seckey (cdk_pkt_seckey_t* dst, cdk_pkt_seckey_t src) +{ + cdk_pkt_seckey_t k; + cdk_mpi_t a; + cdk_s2k_t s2k; + int i; + + if (!dst || !src) + return CDK_Inv_Value; + + k = cdk_calloc (1, sizeof *k); + if (!k) + return CDK_Out_Of_Core; + memcpy (k, src, sizeof *k); + _cdk_copy_pubkey (&k->pk, src->pk); + + if (src->encdata) { + k->encdata = cdk_calloc (1, src->enclen + 1); + if (!k->encdata) + return CDK_Out_Of_Core; + memcpy (k->encdata, src->encdata, src->enclen); + } + + s2k = k->protect.s2k = cdk_calloc (1, sizeof *k->protect.s2k); + if (!k->protect.s2k) + return CDK_Out_Of_Core; + s2k->mode = src->protect.s2k->mode; + s2k->hash_algo = src->protect.s2k->hash_algo; + s2k->count = src->protect.s2k->count; + memcpy (s2k->salt, src->protect.s2k->salt, 8); + + for (i = 0; i < cdk_pk_get_nskey (src->pubkey_algo); i++) { + a = k->mpi[i] = cdk_calloc (1, sizeof **k->mpi + src->mpi[i]->bytes + 2); + if (!k->mpi[i]) + return CDK_Out_Of_Core; + a->bits = src->mpi[i]->bits; + a->bytes = src->mpi[i]->bytes; + /* copy 2 extra bytes (prefix) */ + memcpy (a->data, src->mpi[i]->data, src->mpi[i]->bytes + 2); + } + *dst = k; + + return 0; +} + + +cdk_error_t +_cdk_copy_pk_to_sk( cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk ) +{ + if( !pk || !sk ) + return CDK_Inv_Value; + + sk->version = pk->version; + sk->expiredate = pk->expiredate; + sk->pubkey_algo = pk->pubkey_algo; + sk->has_expired = pk->has_expired; + sk->is_revoked = pk->is_revoked; + sk->main_keyid[0] = pk->main_keyid[0]; + sk->main_keyid[1] = pk->main_keyid[1]; + sk->keyid[0] = pk->keyid[0]; + sk->keyid[1] = pk->keyid[1]; + + return 0; +} + + +cdk_error_t +_cdk_copy_signature (cdk_pkt_signature_t* dst, cdk_pkt_signature_t src) +{ + cdk_pkt_signature_t s = NULL; + struct cdk_subpkt_s *res = NULL; + + if (!dst || !src) + return CDK_Inv_Value; + + s = cdk_calloc (1, sizeof *s); + if (!s) + return CDK_Out_Of_Core; + memcpy (s, src, sizeof *src); + + _cdk_subpkt_copy (&res, src->hashed); + _cdk_subpkt_copy (&s->hashed, res); + cdk_subpkt_free (res); + res = NULL; + _cdk_subpkt_copy (&res, src->unhashed); + _cdk_subpkt_copy (&s->unhashed, res); + cdk_subpkt_free (res); + res = NULL; + *dst = s; + + return 0; +} + + +cdk_error_t +_cdk_pubkey_compare (cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b) +{ + int na, nb, i; + + if (a->timestamp != b->timestamp || a->pubkey_algo != b->pubkey_algo) + return -1; + if (a->version < 4 && a->expiredate != b->expiredate) + return -1; + na = cdk_pk_get_npkey (a->pubkey_algo); + nb = cdk_pk_get_npkey (b->pubkey_algo); + if (na != nb) + return -1; + + for (i = 0; i < na; i++) { + if (memcmp (a->mpi[i]->data, b->mpi[i]->data, a->mpi[i]->bytes)) + return -1; + } + + return 0; +} + + +/** + * cdk_subpkt_free: + * @ctx: the sub packet node to free + * + * Release the context. + **/ +void +cdk_subpkt_free( cdk_subpkt_t ctx ) +{ + cdk_subpkt_t s; + + while( ctx ) { + s = ctx->next; + cdk_free( ctx ); + ctx = s; + } +} + + +/** + * cdk_subpkt_find: + * @ctx: the sub packet node + * @type: the packet type to find + * + * Find the given packet type in the node. If no packet with this + * type was found, return null otherwise pointer to the node. + **/ +cdk_subpkt_t +cdk_subpkt_find( cdk_subpkt_t ctx, int type ) +{ + cdk_subpkt_t s; + + /* xxx: add some code for the case there are more than one sub packet + with the same type. */ + for( s = ctx; s; s = s->next ) { + if( s->type == type ) + return s; + } + + return NULL; +} + + +/** + * cdk_subpkt_new: + * @size: the size of the new context + * + * Create a new sub packet node with the size of @size. + **/ +cdk_subpkt_t +cdk_subpkt_new( size_t size ) +{ + cdk_subpkt_t s; + + if( !size ) + return NULL; + s = cdk_calloc( 1, sizeof *s + size + 1 ); + if( !s ) + return NULL; + return s; +} + + +/** + * cdk_subpkt_get_data: + * @ctx: the sub packet node + * @r_type: pointer store the packet type + * @r_nbytes: pointer to store the packet size + * + * Extract the data from the given sub packet. The type is returned + * in @r_type and the size in @r_nbytes. + **/ +const byte * +cdk_subpkt_get_data( cdk_subpkt_t ctx, int * r_type, size_t * r_nbytes ) +{ + if( !ctx || !r_nbytes ) + return NULL; + if( r_type ) + *r_type = ctx->type; + *r_nbytes = ctx->size; + return ctx->d; +} + + +/** + * cdk_subpkt_add: + * @root: the root node + * @node: the node to add + * + * Add the node in @node to the root node @root. + **/ +cdk_error_t +cdk_subpkt_add( cdk_subpkt_t root, cdk_subpkt_t node ) +{ + cdk_subpkt_t n1; + + if( !root ) + return CDK_Inv_Value; + for( n1 = root; n1->next; n1 = n1->next ) + ; + n1->next = node; + return 0; +} + + +byte * +_cdk_subpkt_get_array( cdk_subpkt_t s, int count, size_t * r_nbytes ) +{ + cdk_subpkt_t list; + byte * buf; + int n, nbytes; + + if( !s ) { + if( r_nbytes ) + *r_nbytes = 0; + return NULL; + } + + for( n=0, list = s; list; list = list->next ) { + n += list->size + 1; + if( list->size < 192 ) n++; + else if( list->size < 8384 ) n += 2; + else n += 5; + } + buf = cdk_calloc( 1, n+1 ); + if( !buf ) + return NULL; + + n = 0; + for( list = s; list; list = list->next ) { + nbytes = 1 + list->size; /* type */ + if( nbytes < 192 ) + buf[n++] = nbytes; + else if( nbytes < 8384 ) { + buf[n++] = nbytes / 256 + 192; + buf[n++] = nbytes % 256; + } + else { + buf[n++] = 0xFF; + buf[n++] = nbytes >> 24; + buf[n++] = nbytes >> 16; + buf[n++] = nbytes >> 8; + buf[n++] = nbytes; + } + buf[n++] = list->type; + memcpy( buf + n, list->d, list->size ); + n += list->size; + } + if( count ) { + cdk_free( buf ); + buf = NULL; + } + if( r_nbytes ) + *r_nbytes = n; + return buf; +} + + +cdk_error_t +_cdk_subpkt_copy( cdk_subpkt_t * r_dst, cdk_subpkt_t src ) +{ + cdk_subpkt_t root, p, node; + + if (!src || !r_dst) + return CDK_Inv_Value; + + root = NULL; + for (p = src; p; p = p->next) { + node = cdk_subpkt_new (p->size); + if (node) { + memcpy (node->d, p->d, p->size); + node->type = p->type; + node->size = p->size; + } + if (!root) + root = node; + else + cdk_subpkt_add (root, node); + } + *r_dst = root; + return 0; +} + + +cdk_error_t +_cdk_subpkt_hash( cdk_subpkt_t hashed, size_t * r_nbytes, cdk_md_hd_t hd ) +{ + byte * p, buf[2]; + size_t nbytes; + + p = _cdk_subpkt_get_array (hashed, 0, &nbytes); + if (!p) + return CDK_Out_Of_Core; + if (nbytes > 65535) + return CDK_Inv_Value; + buf[0] = nbytes >> 8; + buf[1] = nbytes; + cdk_md_write (hd, buf, 2); + cdk_md_write (hd, p, nbytes); + if (r_nbytes) + *r_nbytes = nbytes; + return 0; +} + + +/** + * cdk_subpkt_init: + * @node: the sub packet node + * @type: type of the packet which data should be initialized + * @buf: the buffer with the actual data + * @buflen: the size of the data + * + * Set the packet data of the given root and set the type of it. + **/ +void +cdk_subpkt_init( cdk_subpkt_t node, int type, const void *buf, size_t buflen ) +{ + if( node ) { + node->type = type; + node->size = buflen; + memcpy( node->d, buf, buflen ); + } +} + + +const byte* +cdk_key_desig_revoker_walk( cdk_desig_revoker_t root, + cdk_desig_revoker_t * ctx, + int *r_class, int *r_algid ) +{ + cdk_desig_revoker_t n; + + if( !*ctx ) { + *ctx = root; + n = root; + } + else { + n = (*ctx)->next; + *ctx = n; + } + if( n && r_class && r_algid ) { + *r_class = n->class; + *r_algid = n->algid; + } + return n? n->fpr : NULL; +} |