Ejemplo n.º 1
0
/**
 * gnutls_openpgp_key_get_id - Gets the keyID
 * @key: the structure 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_key_get_id (gnutls_openpgp_key_t key, unsigned char keyid[8])
{
  cdk_packet_t pkt;
  cdk_pkt_pubkey_t pk = NULL;
  uint32_t kid[2];

  if (!key || !keyid)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  pkt = cdk_kbnode_find_packet (key->knode, 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];

  return 0;
}
Ejemplo n.º 2
0
/* Return the key ID from the given packet.
   If this is not possible, 0 is returned */
u32
_cdk_pkt_get_keyid (cdk_packet_t pkt, u32 * keyid)
{
    u32 lowbits;

    if (!pkt)
        return 0;

    switch (pkt->pkttype)
    {
    case CDK_PKT_PUBLIC_KEY:
    case CDK_PKT_PUBLIC_SUBKEY:
        lowbits = cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
        break;

    case CDK_PKT_SECRET_KEY:
    case CDK_PKT_SECRET_SUBKEY:
        lowbits = cdk_sk_get_keyid (pkt->pkt.secret_key, keyid);
        break;

    case CDK_PKT_SIGNATURE:
        lowbits = cdk_sig_get_keyid (pkt->pkt.signature, keyid);
        break;

    default:
        lowbits = 0;
        break;
    }

    return lowbits;
}
Ejemplo n.º 3
0
/* 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;
}
Ejemplo n.º 4
0
/**
 * cdk_sk_get_keyid:
 * @sk: the secret key
 * @keyid: buffer to hold the key ID
 * 
 * Calculate the key ID of the secret key, actually the public key.
 **/
u32 cdk_sk_get_keyid(cdk_pkt_seckey_t sk, u32 * keyid)
{
	u32 lowbits = 0;

	if (sk && sk->pk) {
		lowbits = cdk_pk_get_keyid(sk->pk, keyid);
		sk->keyid[0] = sk->pk->keyid[0];
		sk->keyid[1] = sk->pk->keyid[1];
	}

	return lowbits;
}
Ejemplo n.º 5
0
/**
 * 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;
}
Ejemplo n.º 6
0
static int
xml_add_key (gnutls_string * xmlkey, int ext, cdk_pkt_pubkey_t pk, int sub)
{
  const char *algo, *s;
  char keyid[16], fpr[41], tmp[32];
  uint8_t fingerpr[20];
  unsigned int 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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
static int
keydb_parse_allsigs( cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check )
{
    cdk_kbnode_t node, kb;
    cdk_pkt_signature_t sig;
    cdk_pkt_pubkey_t pk;
    struct cdk_subpkt_s * s = NULL;
    u32 expiredate = 0, curtime = _cdk_timestamp ();
    u32 keyid[2];
    int rc = 0;

    if( !knode )
        return CDK_Inv_Value;
    if( check && !hd )
        return CDK_Inv_Mode;

    kb = cdk_kbnode_find( knode, CDK_PKT_SECRET_KEY );
    if( kb )
        return 0;

    /* reset */
    for( node = knode; node; node = node->next ) {
        if( node->pkt->pkttype == CDK_PKT_USER_ID )
            node->pkt->pkt.user_id->is_revoked = 0;
        else if( node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
                 || node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY )
            node->pkt->pkt.public_key->is_revoked = 0;
    }

    kb = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY );
    if( !kb )
        return CDK_Inv_Packet;
    cdk_pk_get_keyid( kb->pkt->pkt.public_key, keyid );
  
    for( node = knode; node; node = node->next) {
        if( node->pkt->pkttype == CDK_PKT_SIGNATURE ) {
            sig = node->pkt->pkt.signature;
            /* Revocation certificates for primary keys */
            if( sig->sig_class == 0x20 ) {
                kb = cdk_kbnode_find_prev( knode, node, CDK_PKT_PUBLIC_KEY );
                if( kb ) {
                    kb->pkt->pkt.public_key->is_revoked = 1;
                    if( check )
                        _cdk_pk_check_sig (hd, kb, node, NULL);
		}
                else
                    return CDK_Error_No_Key;
	    }
            /* Revocation certificates for subkeys */
            else if( sig->sig_class == 0x28 ) {
                kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
                if( kb ) {
                    kb->pkt->pkt.public_key->is_revoked = 1;
                    if( check )
                        _cdk_pk_check_sig( hd, kb, node, NULL );
		}
                else
                    return CDK_Error_No_Key;
	    }
            /* Revocation certifcates for user ID's */
            else if( sig->sig_class == 0x30 ) {
                if( sig->keyid[0] != keyid[0] || sig->keyid[1] != keyid[1] )
                    continue; /* revokes an earlier signature, no userID. */
                kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_USER_ID);
                if( kb ) {
                    kb->pkt->pkt.user_id->is_revoked = 1;
                    if( check )
                        _cdk_pk_check_sig( hd, kb, node, NULL );
		}
                else
                    return CDK_Error_No_Key;
	    }
            /* Direct certificates for primary keys */
            else if( sig->sig_class == 0x1F ) {
                kb = cdk_kbnode_find_prev( knode, node, CDK_PKT_PUBLIC_KEY );
                if( kb ) {
                    pk = kb->pkt->pkt.public_key;
                    pk->is_invalid = 0;
                    s = cdk_subpkt_find( node->pkt->pkt.signature->hashed,
                                         CDK_SIGSUBPKT_KEY_EXPIRE );
                    if( s ) {
                        expiredate = _cdk_buftou32( s->d );
                        pk->expiredate = pk->timestamp + expiredate;
                        pk->has_expired = pk->expiredate > curtime? 0 : 1;
		    }
                    if( check )
                        _cdk_pk_check_sig( hd, kb, node, NULL );
		}
                else
                    return CDK_Error_No_Key;
	    }
            /* Direct certificates for subkeys */
            else if( sig->sig_class == 0x18 ) {
                kb = cdk_kbnode_find_prev( knode, node, CDK_PKT_PUBLIC_SUBKEY);
                if( kb ) {
                    pk = kb->pkt->pkt.public_key;
                    pk->is_invalid = 0;
                    s = cdk_subpkt_find( node->pkt->pkt.signature->hashed,
                                         CDK_SIGSUBPKT_KEY_EXPIRE );
                    if( s ) {
                        expiredate = _cdk_buftou32( s->d );
                        pk->expiredate = pk->timestamp + expiredate;
                        pk->has_expired = pk->expiredate > curtime? 0 : 1;
		    }
                    if( check )
                        _cdk_pk_check_sig( hd, kb, node, NULL );
		}
                else
                    return CDK_Error_No_Key;
	    }
	}
    }
    node = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY );
    if( node && node->pkt->pkt.public_key->version == 3 ) {
        /* v3 public keys have no additonal signatures for the key directly.
           we say the key is valid when we have at least a self signature. */
        pk = node->pkt->pkt.public_key;
        for( node = knode; node; node = node->next ) {
            if( is_selfsig( node, keyid ) ) {
                pk->is_invalid = 0;
                break;
            }
        }
    }
    if( node && (node->pkt->pkt.public_key->is_revoked
                 || node->pkt->pkt.public_key->has_expired) ) {
        /* if the primary key has been revoked, mark all subkeys as invalid
           because without a primary key they are not useable */
        for( node = knode; node; node = node->next ) {
            if( node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY )
                node->pkt->pkt.public_key->is_invalid = 1;
        }
    }
    return rc;
}