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; }
static cdk_error_t read_subpkt (cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes) { byte c, c1; size_t size, nread, n; cdk_subpkt_t node; cdk_error_t rc; if (!inp || !r_nbytes) return CDK_Inv_Value; if (DEBUG_PKT) _cdk_log_debug ("read_subpkt:\n"); n = 0; *r_nbytes = 0; c = cdk_stream_getc (inp); n++; if (c == 255) { size = read_32 (inp); n += 4; } else if (c >= 192 && c < 255) { c1 = cdk_stream_getc (inp); n++; if (c1 == 0) return 0; size = ((c - 192) << 8) + c1 + 192; } else if (c < 192) size = c; else return CDK_Inv_Packet; node = cdk_subpkt_new (size); if (!node) return CDK_Out_Of_Core; node->size = size; node->type = cdk_stream_getc (inp); if (DEBUG_PKT) _cdk_log_debug (" %d octets %d type\n", node->size, node->type); n++; node->size--; rc = stream_read (inp, node->d, node->size, &nread); n += nread; if (rc) return rc; *r_nbytes = n; if (!*r_ctx) *r_ctx = node; else cdk_subpkt_add (*r_ctx, node); return rc; }
/** * 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; }
static cdk_pkt_signature_t sig_subkey_create( cdk_keygen_ctx_t hd ) { cdk_md_hd_t md; cdk_subpkt_t node; cdk_pkt_signature_t sig; cdk_pkt_pubkey_t pk = hd->key[0].pk; cdk_pkt_pubkey_t sub_pk = hd->key[1].pk; cdk_pkt_seckey_t sk = hd->key[0].sk; byte buf[4]; int rc; sig = cdk_calloc( 1, sizeof * sig ); if( !sig ) return NULL; _cdk_sig_create( pk, sig ); sig->sig_class = 0x18; sig->digest_algo = CDK_MD_SHA1; if( sub_pk->expiredate ) { _cdk_u32tobuf( sub_pk->expiredate - sub_pk->timestamp, buf ); node = cdk_subpkt_new( 4 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_KEY_EXPIRE, buf, 4 ); cdk_subpkt_add( sig->hashed, node ); } } md = cdk_md_open( sig->digest_algo, 0 ); if( !md ) { _cdk_free_signature( sig ); return NULL; } _cdk_hash_pubkey( pk, md, 0 ); _cdk_hash_pubkey( sub_pk, md, 0 ); rc = _cdk_sig_complete( sig, sk, md ); cdk_md_close( md ); if( rc ) { _cdk_free_signature( sig ); return NULL; } return sig; }
static cdk_pkt_signature_t sig_self_create( cdk_keygen_ctx_t hd ) { cdk_md_hd_t md; cdk_subpkt_t node; cdk_pkt_signature_t sig; cdk_pkt_pubkey_t pk = hd->key[0].pk; cdk_pkt_userid_t id = hd->id; cdk_pkt_seckey_t sk = hd->key[0].sk; u32 keyid[2]; byte buf[8], * p; int rc; sig = cdk_calloc( 1, sizeof * sig ); if( !sig ) return NULL; sig->version = 4; sig->timestamp = _cdk_timestamp( ); sig->sig_class = 0x13; sig->pubkey_algo = hd->key[0].algo; sig->digest_algo = CDK_MD_SHA1; _cdk_u32tobuf( sig->timestamp, buf ); sig->hashed = node = cdk_subpkt_new( 4 ); if( node ) cdk_subpkt_init( node, CDK_SIGSUBPKT_SIG_CREATED, buf, 4 ); p = hd->sym_prefs; node = cdk_subpkt_new( hd->sym_len + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_SYM, p, hd->sym_len ); cdk_subpkt_add( sig->hashed, node ); } p = hd->hash_prefs; node = cdk_subpkt_new( hd->hash_len + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_HASH, p, hd->hash_len ); cdk_subpkt_add( sig->hashed, node ); } p = hd->zip_prefs; node = cdk_subpkt_new( hd->zip_len + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_ZIP, p, hd->zip_len ); cdk_subpkt_add( sig->hashed, node ); } if( hd->mdc_feature ) { buf[0] = 0x01; node = cdk_subpkt_new( 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_FEATURES, buf, 1 ); cdk_subpkt_add( sig->hashed, node ); } } if( hd->ks_no_modify ) { buf[0] = 0x80; node = cdk_subpkt_new( 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_KS_FLAGS, buf, 1 ); cdk_subpkt_add( sig->hashed, node ); } } if( hd->ks_pref_url ) { node = cdk_subpkt_new( strlen( hd->ks_pref_url ) + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREF_KS, hd->ks_pref_url, strlen( hd->ks_pref_url ) ); cdk_subpkt_add( sig->hashed, node ); } } if( pk->expiredate ) { node = cdk_subpkt_new( 4 ); if( node ) { _cdk_u32tobuf( pk->expiredate - pk->timestamp, buf ); cdk_subpkt_init( node, CDK_SIGSUBPKT_KEY_EXPIRE, buf, 4 ); cdk_subpkt_add( sig->hashed, node ); } } sig->unhashed = node = cdk_subpkt_new( 8 ); if( node ) { cdk_pk_get_keyid( pk, keyid ); _cdk_u32tobuf( keyid[0], buf ); _cdk_u32tobuf( keyid[1], buf + 4 ); cdk_subpkt_init( node, CDK_SIGSUBPKT_ISSUER, buf, 8 ); } md = cdk_md_open( sig->digest_algo, 0 ); if( !md ) { _cdk_free_signature( sig ); return NULL; } _cdk_hash_pubkey( pk, md, 0 ); _cdk_hash_userid( id, sig->version == 4, md ); rc = _cdk_sig_complete( sig, sk, md ); cdk_md_close( md ); if( rc ) { _cdk_free_signature( sig ); return NULL; } return sig; }