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; *dst = NULL; 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); if (src->selfsig) _cdk_copy_signature (&u->selfsig, src->selfsig); *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; *dst = NULL; 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] = _gnutls_mpi_copy(src->mpi[i]); *dst = k; return 0; }
static int keydb_merge_selfsig( cdk_kbnode_t key, u32 * keyid ) { cdk_kbnode_t node, kbnode, unode; cdk_subpkt_t s = NULL; cdk_pkt_signature_t sig = NULL; cdk_pkt_userid_t uid = NULL; const byte * symalg = NULL, * hashalg = NULL, * compalg = NULL; size_t nsymalg = 0, nhashalg = 0, ncompalg = 0, n = 0; int key_usage = 0, key_expire = 0; if (!key) return CDK_Inv_Value; for( node = key; node; node = node->next ) { if( !is_selfsig( node, keyid ) ) continue; unode = cdk_kbnode_find_prev( key, node, CDK_PKT_USER_ID ); if( !unode ) return CDK_Error_No_Key; uid = unode->pkt->pkt.user_id; sig = node->pkt->pkt.signature; s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PRIMARY_UID ); if( s ) uid->is_primary = 1; s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_FEATURES ); if( s && s->size == 1 && s->d[0] & 0x01 ) uid->mdc_feature = 1; s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_KEY_EXPIRE ); if( s && s->size == 4 ) key_expire = _cdk_buftou32( s->d ); s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_KEY_FLAGS ); if( s ) { if( s->d[0] & 3 ) /* cert + sign data */ key_usage |= PK_USAGE_SIGN; if( s->d[0] & 12 ) /* encrypt comm. + storage */ key_usage |= PK_USAGE_ENCR; } s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PREFS_SYM ); if( s ) { symalg = s->d; nsymalg = s->size; n += s->size + 1; } s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PREFS_HASH ); if( s ) { hashalg = s->d; nhashalg = s->size; n += s->size + 1; } s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PREFS_ZIP ); if( s ) { compalg = s->d; ncompalg = s->size; n += s->size + 1; } if( !n || !hashalg || !compalg || !symalg ) uid->prefs = NULL; else { uid->prefs = cdk_calloc( 1, sizeof (*uid->prefs) * (n + 1) ); if( !uid->prefs ) return CDK_Out_Of_Core; n = 0; for( ; nsymalg; nsymalg--, n++ ) { uid->prefs[n].type = CDK_PREFTYPE_SYM; uid->prefs[n].value = *symalg++; } for( ; nhashalg; nhashalg--, n++ ) { uid->prefs[n].type = CDK_PREFTYPE_HASH; uid->prefs[n].value = *hashalg++; } for( ; ncompalg; ncompalg--, n++ ) { uid->prefs[n].type = CDK_PREFTYPE_ZIP; uid->prefs[n].value = *compalg++; } /* end of list marker */ uid->prefs[n].type = CDK_PREFTYPE_NONE; uid->prefs[n].value = 0; uid->prefs_size = n; kbnode = cdk_kbnode_find_prev( key, node, CDK_PKT_PUBLIC_KEY ); if( kbnode ) { cdk_pkt_pubkey_t pk = kbnode->pkt->pkt.public_key; if( uid->prefs && n ) { pk->prefs = _cdk_copy_prefs( uid->prefs ); pk->prefs_size = n; } if( key_expire ) { pk->expiredate = pk->timestamp + key_expire; pk->has_expired = pk->expiredate> _cdk_timestamp ()?0 :1; } if( key_usage && !pk->pubkey_usage ) pk->pubkey_usage = key_usage; pk->is_invalid = 0; } } } return 0; }