/** * cdk_stream_close: Close a stream and flush all buffers. * @s: The STREAM object. * * This function work different for read or write streams. When the * stream is for reading, the filtering is already done and we can * simply close the file and all buffers. * But for the case it's a write stream, we need to apply all registered * filters now. The file is closed in the filter function and not here. **/ cdk_error_t cdk_stream_close( cdk_stream_t s ) { struct stream_filter_s * f, * f2; int rc = 0; if( !s ) return CDK_Inv_Value; _cdk_log_debug( "close stream `%s'\n", s->fname? s->fname : "[temp]" ); if( !s->flags.filtrated && !s->error ) rc = cdk_stream_flush( s ); if( s->fname || s->flags.temp ) { rc = fclose( s->fp ); s->fp = NULL; if( rc ) rc = CDK_File_Error; } f = s->filters; while( f ) { f2 = f->next; if( f->fnct ) f->fnct( f->opaque, STREAMCTL_FREE, NULL, NULL ); cdk_free( f ); f = f2; } if( s->fname ) { cdk_free( s->fname ); s->fname = NULL; } cdk_free( s ); return rc; }
/** * cdk_stream_new: Create a new stream into into the given file. * @file: The name of the new file * @ret_s: The new STREAM object **/ cdk_error_t cdk_stream_new( const char * file, cdk_stream_t * ret_s ) { cdk_stream_t s; if( !ret_s ) return CDK_Inv_Value; _cdk_log_debug( "new stream `%s'\n", file? file : "[temp]" ); *ret_s = NULL; s = cdk_calloc( 1, sizeof *s ); if( !s ) return CDK_Out_Of_Core; s->flags.write = 1; if( !file ) s->flags.temp = 1; else { s->fname = cdk_strdup( file ); if( !s->fname ) { cdk_free( s ); return CDK_Out_Of_Core; } } s->fp = tmpfile( ); if( !s->fp ) { cdk_free( s->fname ); cdk_free( s ); return CDK_File_Error; } *ret_s = s; return 0; }
static int keydb_idx_search( cdk_stream_t inp, u32 * keyid, const byte * fpr, u32 * r_off ) { key_idx_t idx; if( !inp || !r_off ) return CDK_Inv_Value; if( (keyid && fpr) || (!keyid && !fpr) ) return CDK_Inv_Mode; *r_off = 0xFFFFFFFF; cdk_stream_seek( inp, 0 ); while( keydb_idx_parse( inp, &idx ) != CDK_EOF ) { if( keyid && KEYID_CMP( keyid, idx->keyid ) ) { *r_off = idx->offset; break; } else if( fpr && !memcmp( idx->fpr, fpr, 20 ) ) { *r_off = idx->offset; break; } cdk_free( idx ); idx = NULL; } cdk_free( idx ); return *r_off != 0xFFFFFFFF ? 0 : CDK_EOF; }
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_pk_release (pkt->pkt.public_key); break; case CDK_PKT_SECRET_KEY : case CDK_PKT_SECRET_SUBKEY: cdk_sk_release (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; } /* Reset the packet type to avoid, when cdk_pkt_release() will be used, that the second cdk_pkt_free() call will double free the data. */ pkt->pkttype = 0; }
/** * cdk_stream_open: create a new stream based on an existing file. * @file: The file to open * @ret_s: The new STREAM object **/ cdk_error_t cdk_stream_open( const char * file, cdk_stream_t * ret_s ) { cdk_stream_t s; if( !file || !ret_s ) return CDK_Inv_Value; _cdk_log_debug( "open stream `%s'\n", file ); *ret_s = NULL; s = cdk_calloc( 1, sizeof *s ); if( !s ) return CDK_Out_Of_Core; s->fname = cdk_strdup( file ); if( !s->fname ) { cdk_free( s ); return CDK_Out_Of_Core; } s->fp = fopen( file, "rb" ); if( !s->fp ) { cdk_free( s->fname ); cdk_free( s ); return CDK_File_Error; } s->flags.write = 0; *ret_s = s; return 0; }
void _cdk_result_verify_free (cdk_verify_result_t res) { if (!res) return; cdk_free (res->policy_url); cdk_free (res->sig_data); cdk_free (res); }
void keydb_search_free( cdk_dbsearch_t dbs ) { if( !dbs ) return; if( dbs->type == CDK_DBSEARCH_EXACT || dbs->type == CDK_DBSEARCH_SUBSTR ) cdk_free( dbs->u.pattern ); dbs->type = 0; cdk_free( dbs ); }
/** * cdk_pk_from_secret_key: * @sk: the secret key * @ret_pk: the new public key * * Create a new public key from a secret key. **/ cdk_error_t cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t *ret_pk) { if (!sk) return CDK_Inv_Value; return _cdk_copy_pubkey (ret_pk, sk->pk); } #if 0 /* FIXME: Code is not finished yet. */ cdk_error_t cdk_pk_revoke_cert_create (cdk_pkt_seckey_t sk, int code, const char *inf, char **ret_revcert) { gcry_md_hd_t md; cdk_subpkt_t node; cdk_pkt_signature_t sig; char *p = NULL, *dat; gcry_error_t err; cdk_error_t rc = 0; size_t n; if (!sk || !ret_revcert) return CDK_Inv_Value; if(code < 0 || code > 3) return CDK_Inv_Value; sig = cdk_calloc (1, sizeof *sig); if (!sig) return CDK_Out_Of_Core; _cdk_sig_create (sk->pk, sig); n = 1; if (inf) { n += strlen (p); p = cdk_utf8_encode (inf); } dat = cdk_calloc (1, n+1); if (!dat) { _cdk_free_signature (sig); return CDK_Out_Of_Core; } dat[0] = code; if (inf) memcpy (dat+1, p, strlen (p)); cdk_free (p); node = cdk_subpkt_new (n); if (node) { cdk_subpkt_init (node, CDK_SIGSUBPKT_REVOC_REASON, dat, n); cdk_subpkt_add (sig->hashed, node); } cdk_free (dat); err = gcry_md_open (&md, GCRY_MD_SHA1, 0); if (err) rc = map_gcry_error (err); else _cdk_hash_pubkey (sk->pk, md, 0); _cdk_free_signature (sig); return rc; }
/* This functions builds an index of the keyring into a separate file with the name keyring.ext.idx. It contains the offset of all public- and public subkeys. The format of the file is: -------- 4 octets offset of the packet 8 octets keyid 20 octets fingerprint -------- We store the keyid and the fingerprint due to the fact we can't get the keyid from a v3 fingerprint directly. */ static int keydb_idx_build( const char * file ) { cdk_packet_t pkt; cdk_stream_t inp, out = NULL; byte buf[8], fpr[20]; char * fname; u32 keyid[2]; int rc, pos; if( !file ) return CDK_Inv_Value; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; fname = keydb_idx_mkname( file ); if( !fname ) { rc = CDK_Out_Of_Core; goto leave; } rc = cdk_stream_open( file, &inp ); if( !rc ) rc = cdk_stream_create( fname, &out ); if( rc ) goto leave; while( !cdk_stream_eof( inp ) ) { pos = cdk_stream_tell( inp ); rc = cdk_pkt_read( inp, pkt ); if( rc ) break; if( pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ) { _cdk_u32tobuf( pos, buf ); cdk_stream_write( out, buf, 4 ); cdk_pk_get_keyid( pkt->pkt.public_key, keyid ); _cdk_u32tobuf( keyid[0], buf ); _cdk_u32tobuf( keyid[1], buf + 4 ); cdk_stream_write( out, buf, 8 ); cdk_pk_get_fingerprint( pkt->pkt.public_key, fpr ); cdk_stream_write( out, fpr, 20 ); } cdk_pkt_free( pkt ); cdk_pkt_init( pkt ); } cdk_stream_close( out ); leave: cdk_stream_close( inp ); cdk_free( fname ); cdk_free( pkt ); return rc; }
/** * cdk_listkey_close: * @ctx: the list key context * * Free the list key context. **/ void cdk_listkey_close( cdk_listkey_t ctx ) { if( ctx ) { if( ctx->type ) cdk_free( ctx->u.patt ); else cdk_strlist_free( ctx->u.fpatt ); cdk_free( ctx ); } }
/** * cdk_pk_sign: * @sk: secret key * @sig: signature * @md: the message digest * * Sign the message digest from @md and write the result into @sig. **/ cdk_error_t cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, const byte *md) { gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL; byte *encmd = NULL; size_t enclen = 0; int nbits; cdk_error_t rc; gcry_error_t err; if (!sk || !sk->pk || !sig || !md) return CDK_Inv_Value; if (!is_unprotected (sk)) return CDK_Inv_Mode; if (!KEY_CAN_SIGN (sig->pubkey_algo)) return CDK_Inv_Algo; nbits = cdk_pk_get_nbits (sk->pk); rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, sk->pk->pubkey_algo, md, sig->digest_algo, nbits); if (rc) return rc; rc = seckey_to_sexp (&s_skey, sk); if (!rc) rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen); if (rc) { cdk_free (encmd); gcry_sexp_release (s_skey); return rc; } err = gcry_pk_sign (&s_sig, s_hash, s_skey); if (err) rc = map_gcry_error (err); else { rc = sexp_to_sig (sig, s_sig); if (!rc) { sig->digest_start[0] = md[0]; sig->digest_start[1] = md[1]; } } gcry_sexp_release (s_skey); gcry_sexp_release (s_hash); gcry_sexp_release (s_sig); cdk_free (encmd); return rc; }
void _cdk_free_userid(cdk_pkt_userid_t uid) { if (!uid) return; cdk_free(uid->prefs); uid->prefs = NULL; cdk_free(uid->attrib_img); uid->attrib_img = NULL; cdk_free(uid); }
/** * cdk_pklist_encrypt: * @pkl: the keylist * @dek: the data encryption key * @outp: the stream to write in the data * * Encrypt the session key with each key of the list and wrap it * into a PUBKEY_ENC packet and write it to @outp. */ cdk_error_t cdk_pklist_encrypt( cdk_keylist_t pk_list, cdk_dek_t dek, cdk_stream_t outp ) { cdk_pkt_pubkey_t pk = NULL; cdk_pkt_pubkey_enc_t enc = NULL; cdk_packet_t pkt; cdk_sesskey_t frame = NULL; int nbits = 0; int rc = 0; if( !pk_list || !dek || !outp ) return CDK_Inv_Value; if( pk_list->type != CDK_PKT_PUBLIC_KEY ) return CDK_Inv_Mode; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; for( ; pk_list; pk_list = pk_list->next ) { pk = pk_list->key.pk; cdk_free( enc ); enc = cdk_calloc( 1, sizeof *enc ); if( !enc ) return CDK_Out_Of_Core; enc->version = 3; enc->pubkey_algo = pk->pubkey_algo; cdk_pk_get_keyid( pk, enc->keyid ); nbits = cdk_pk_get_nbits( pk ); rc = cdk_dek_encode_pkcs1( dek, nbits, &frame ); if( rc ) break; rc = cdk_pk_encrypt( pk, enc, frame ); cdk_sesskey_free( frame ); if( rc ) break; else { cdk_pkt_init( pkt ); pkt->old_ctb = dek->rfc1991? 1 : 0; pkt->pkttype = CDK_PKT_PUBKEY_ENC; pkt->pkt.pubkey_enc = enc; rc = cdk_pkt_write( outp, pkt ); cdk_pkt_free( pkt ); if( rc ) break; } } cdk_free( pkt ); cdk_free( enc ); return rc; }
void cdk_pk_release(cdk_pubkey_t pk) { size_t npkey; if (!pk) return; npkey = cdk_pk_get_npkey(pk->pubkey_algo); _cdk_free_userid(pk->uid); pk->uid = NULL; cdk_free(pk->prefs); pk->prefs = NULL; _cdk_free_mpibuf(npkey, pk->mpi); cdk_free(pk); }
/* Detach the openpgp packet from the packet structure and release the packet structure itself. */ void _cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx) { /* For now we just allow this for keys. */ switch (pkt->pkttype) { case CDK_PKT_PUBLIC_KEY: case CDK_PKT_PUBLIC_SUBKEY: *ctx = pkt->pkt.public_key; break; case CDK_PKT_SECRET_KEY: case CDK_PKT_SECRET_SUBKEY: *ctx = pkt->pkt.secret_key; break; default: *r_pkttype = 0; return; } /* The caller might expect a specific packet type and is not interested to store it for later use. */ if (r_pkttype) *r_pkttype = pkt->pkttype; cdk_free (pkt); }
cdk_error_t _cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx) { cdk_packet_t pkt; cdk_error_t rc; rc = cdk_pkt_new (&pkt); if (rc) return rc; switch (pkttype) { case CDK_PKT_PUBLIC_KEY: case CDK_PKT_PUBLIC_SUBKEY: pkt->pkt.public_key = pktctx; break; case CDK_PKT_SIGNATURE: pkt->pkt.signature = pktctx; break; case CDK_PKT_SECRET_KEY: case CDK_PKT_SECRET_SUBKEY: pkt->pkt.secret_key = pktctx; break; case CDK_PKT_USER_ID: pkt->pkt.user_id = pktctx; break; } pkt->pkttype = pkttype; rc = cdk_pkt_write (out, pkt); cdk_free (pkt); return rc; }
/** * cdk_pkt_release: * @pkt: the packet * * Free the contents of the given package and * release the memory of the structure. **/ void cdk_pkt_release(cdk_packet_t pkt) { if (!pkt) return; cdk_pkt_free(pkt); cdk_free(pkt); }
static void free_symkey_enc (cdk_pkt_symkey_enc_t enc) { if (!enc) return; cdk_s2k_free (enc->s2k); cdk_free (enc); }
/** * cdk_keygen_set_name: set the userid name for the key * @hd: the keygen object * @name: name * * The name will be encoded in UTF8 to avoid problems. **/ void cdk_keygen_set_name( cdk_keygen_ctx_t hd, const char * name ) { if( hd ) { cdk_free( hd->user_id ); hd->user_id = cdk_utf8_encode( name ); } }
void cdk_sk_release(cdk_seckey_t sk) { size_t nskey; if (!sk) return; nskey = cdk_pk_get_nskey(sk->pubkey_algo); _cdk_free_mpibuf(nskey, sk->mpi); cdk_free(sk->encdata); sk->encdata = NULL; cdk_pk_release(sk->pk); sk->pk = NULL; cdk_s2k_free(sk->protect.s2k); sk->protect.s2k = NULL; cdk_free(sk); }
static void free_literal(cdk_pkt_literal_t pt) { if (!pt) return; /* The buffer which is referenced in this packet is closed elsewhere. To close it here would cause a double close. */ cdk_free(pt); }
/** * cdk_stream_write: * @s: The STREAM object * @buf: The buffer with the values to write. * @count: The size of the buffer. * * Tries to write count bytes into the stream. * In this function we simply write the bytes to the stream. We can't * use the filters here because it would mean they have to support * partial flushing. **/ int cdk_stream_write (cdk_stream_t s, const void *buf, size_t count) { int nwritten; if (!s) { s->error = CDK_Inv_Value; gnutls_assert(); return EOF; } if (s->cbs_hd) { if (s->cbs.write) return s->cbs.write (s->cbs_hd, buf, count); return 0; } if (!s->flags.write) { s->error = CDK_Inv_Mode; /* this is a read stream */ gnutls_assert(); return EOF; } if (!buf && !count) return stream_flush (s); if (s->cache.on) { /* We need to resize the buffer if the additional data wouldn't fit into it. We allocate more memory to avoid to resize it the next time the function is used. */ if (s->cache.size + count > s->cache.alloced) { byte *old = s->cache.buf; s->cache.buf = cdk_calloc (1, s->cache.alloced + count + STREAM_BUFSIZE); s->cache.alloced += (count + STREAM_BUFSIZE); memcpy (s->cache.buf, old, s->cache.size); cdk_free (old); _cdk_log_debug ("stream: enlarge cache to %d octets\n", s->cache.alloced); } memcpy (s->cache.buf + s->cache.size, buf, count); s->cache.size += count; return count; } nwritten = fwrite (buf, 1, count, s->fp); if (!nwritten) nwritten = EOF; return nwritten; }
byte *_cdk_subpkt_get_array(cdk_subpkt_t s, int count, size_t * r_nbytes) { cdk_subpkt_t list; byte *buf; size_t n, nbytes; if (!s) { if (r_nbytes) *r_nbytes = 0; return NULL; } for (n = 0, list = s; list; list = list->next) { n++; /* type */ n += list->size; 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) { nbytes -= 192; buf[n++] = nbytes / 256 + 192; buf[n++] = nbytes & 0xff; } 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; }
void cdk_strlist_free (cdk_strlist_t sl) { cdk_strlist_t sl2; for(; sl; sl = sl2 ) { sl2 = sl->next; cdk_free (sl); } }
/** * 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_keygen_free: free the keygen object * @hd: the keygen object * **/ void cdk_keygen_free( cdk_keygen_ctx_t hd ) { if( hd ) { _cdk_free_pubkey( hd->key[0].pk ); _cdk_free_pubkey( hd->key[1].pk ); _cdk_free_seckey( hd->key[0].sk ); _cdk_free_seckey( hd->key[1].sk ); _cdk_free_userid( hd->id ); _cdk_free_signature( hd->sig ); cdk_free( hd->sym_prefs ); cdk_free( hd->hash_prefs ); cdk_free( hd->zip_prefs ); _cdk_sec_free( hd->pass, hd->pass_len ); _cdk_free_mpibuf( hd->key[0].n, hd->key[0].resarr ); _cdk_free_mpibuf( hd->key[1].n, hd->key[1].resarr ); cdk_free( hd ); } }
/* We encode the MD in this way: * * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) * * PAD consists of FF bytes. */ static cdk_error_t do_encode_md (byte ** r_frame, size_t * r_flen, const byte * md, int algo, size_t len, unsigned nbits, const byte * asn, size_t asnlen) { byte *frame = NULL; size_t nframe = (nbits + 7) / 8; ssize_t i; size_t n = 0; if (!asn || !md || !r_frame || !r_flen) return CDK_Inv_Value; if (len + asnlen + 4 > nframe) return CDK_General_Error; frame = cdk_calloc (1, nframe); if (!frame) return CDK_Out_Of_Core; frame[n++] = 0; frame[n++] = 1; i = nframe - len - asnlen - 3; if (i < 0) { cdk_free (frame); return CDK_Inv_Value; } memset (frame + n, 0xFF, i); n += i; frame[n++] = 0; memcpy (frame + n, asn, asnlen); n += asnlen; memcpy (frame + n, md, len); n += len; if (n != nframe) { cdk_free (frame); return CDK_Inv_Value; } *r_frame = frame; *r_flen = n; return 0; }
static void free_pubkey_enc(cdk_pkt_pubkey_enc_t enc) { size_t nenc; if (!enc) return; nenc = cdk_pk_get_nenc(enc->pubkey_algo); _cdk_free_mpibuf(nenc, enc->mpi); cdk_free(enc); }
/** * cdk_sklist_write: * @skl: secret keylist * @outp: the stream to write in the data * @hash: opaque handle for the message digest operations * @sigclass: the class of the sig * @sigver: version of the sig * * Complete the sig based on @hash and write all signatures to @outp. **/ cdk_error_t cdk_sklist_write( cdk_keylist_t skl, cdk_stream_t outp, cdk_md_hd_t hash, int sigclass, int sigver ) { cdk_keylist_t r = NULL; cdk_pkt_signature_t sig = NULL; cdk_packet_t pkt; cdk_md_hd_t md = NULL; byte * mdbuf; int rc = 0, digest_algo; if( !skl || !outp || !hash ) return CDK_Inv_Value; if( skl->type != CDK_PKT_SECRET_KEY ) return CDK_Inv_Mode; pkt = cdk_calloc( 1, sizeof *pkt ); if( !pkt ) return CDK_Out_Of_Core; digest_algo = cdk_md_get_algo( hash ); for( r = skl; r; r = r->next ) { sig = cdk_calloc( 1, sizeof *sig ); if( !sig ) return CDK_Out_Of_Core; sig->version = sigver; _cdk_sig_create( r->key.sk->pk, sig ); if( sig->digest_algo != digest_algo ) sig->digest_algo = digest_algo; sig->sig_class = sigclass; md = cdk_md_copy( hash ); _cdk_hash_sig_data( sig, md ); cdk_md_final( md ); mdbuf = cdk_md_read( md, sig->digest_algo ); rc = cdk_pk_sign( r->key.sk, sig, mdbuf ); if( rc ) break; cdk_pkt_init( pkt ); pkt->old_ctb = sig->version == 3? 1 : 0; pkt->pkttype = CDK_PKT_SIGNATURE; pkt->pkt.signature = sig; rc = cdk_pkt_write( outp, pkt ); cdk_pkt_free( pkt ); if( rc ) break; cdk_md_close( md ); md = NULL; } cdk_free( pkt ); cdk_md_close( md ); return rc; }
/** * cdk_sklist_release: * @skl: secret keylist * * Free the memory of the secret keylist. **/ void cdk_sklist_release( cdk_keylist_t sk_list ) { cdk_keylist_t sk_rover = NULL; for( ; sk_list; sk_list = sk_rover ) { sk_rover = sk_list->next; _cdk_free_seckey( sk_list->key.sk ); sk_list->key.sk = NULL; cdk_free( sk_list ); } }