Exemple #1
0
static int
keydb_idx_parse( cdk_stream_t inp, key_idx_t * r_idx )
{
    key_idx_t idx;
    byte buf[4];
    int i;

    if( !inp || !r_idx )
        return CDK_Inv_Value;
  
    idx = cdk_calloc( 1, sizeof * idx );
    if( !idx )
        return CDK_Out_Of_Core;

    while( !cdk_stream_eof( inp ) ) {
        i = cdk_stream_read( inp, buf, 4 );
        if( i == CDK_EOF )
            break;
        idx->offset = _cdk_buftou32( buf );
        cdk_stream_read( inp, buf, 4 );
        idx->keyid[0] = _cdk_buftou32( buf );
        cdk_stream_read( inp, buf, 4 );
        idx->keyid[1] = _cdk_buftou32( buf );
        cdk_stream_read( inp, idx->fpr, 20 );
#if 0
        _cdk_log_debug( "%08lu: keyid=%08lX fpr=", idx->offset,idx->keyid[1] );
        for( i = 0; i < 20; i++ )
            _cdk_log_debug( "%02X", idx->fpr[i] );
        _cdk_log_debug( "\n" );
#endif
        break; 
    }
    *r_idx = idx;
    return cdk_stream_eof( inp )? CDK_EOF : 0;  
}
Exemple #2
0
/**
 * cdk_pk_get_keyid:
 * @pk: the public key
 * @keyid: buffer to store the key ID
 * 
 * Calculate the key ID of the given public key.
 **/
u32
cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid)
{
  u32 lowbits = 0;
  byte buf[24];
  
  if (pk && (!pk->keyid[0] || !pk->keyid[1])) 
    {
      if (pk->version < 4 && is_RSA (pk->pubkey_algo)) 
	{
	  byte p[MAX_MPI_BYTES];
	  size_t n;
	  
	  gcry_mpi_print (GCRYMPI_FMT_USG, p, MAX_MPI_BYTES, &n, pk->mpi[0]);
	  pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5];
	  pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1];
	}
      else if (pk->version == 4)
	{
	  cdk_pk_get_fingerprint (pk, buf);
	  pk->keyid[0] = _cdk_buftou32 (buf + 12);
	  pk->keyid[1] = _cdk_buftou32 (buf + 16);
	}
    }
  lowbits = pk ? pk->keyid[1] : 0;
  if (keyid && pk)
    {
      keyid[0] = pk->keyid[0];
      keyid[1] = pk->keyid[1];
    }
  
  return lowbits;
}
Exemple #3
0
/**
 * cdk_pk_fingerprint_get_keyid:
 * @fpr: the key fingerprint
 * @fprlen: the length of the fingerprint
 * 
 * Derive the key ID from the key fingerprint.
 * For version 3 keys, this is not working.
 **/
u32
cdk_pk_fingerprint_get_keyid(const byte * fpr, size_t fprlen, u32 * keyid)
{
	u32 lowbits = 0;

	/* In this case we say the key is a V3 RSA key and we can't
	   use the fingerprint to get the keyid. */
	if (fpr && fprlen == 16) {
		keyid[0] = 0;
		keyid[1] = 0;
		return 0;
	} else if (keyid && fpr) {
		keyid[0] = _cdk_buftou32(fpr + 12);
		keyid[1] = _cdk_buftou32(fpr + 16);
		lowbits = keyid[1];
	} else if (fpr)
		lowbits = _cdk_buftou32(fpr + 16);
	return lowbits;
}
Exemple #4
0
/**
 * cdk_pk_get_keyid:
 * @pk: the public key
 * @keyid: buffer to store the key ID
 * 
 * Calculate the key ID of the given public key.
 **/
u32 cdk_pk_get_keyid(cdk_pubkey_t pk, u32 * keyid)
{
	u32 lowbits = 0;
	byte buf[24];
	int rc;

	if (pk && (!pk->keyid[0] || !pk->keyid[1])) {
		if (pk->version < 4 && is_RSA(pk->pubkey_algo)) {
			byte p[MAX_MPI_BYTES];
			size_t n;

			n = MAX_MPI_BYTES;
			rc = _gnutls_mpi_print(pk->mpi[0], p, &n);
			if (rc < 0 || n < 8) {
				keyid[0] = keyid[1] = (u32)-1;
				return (u32)-1;
			}

			pk->keyid[0] =
			    p[n - 8] << 24 | p[n - 7] << 16 | p[n -
								6] << 8 |
			    p[n - 5];
			pk->keyid[1] =
			    p[n - 4] << 24 | p[n - 3] << 16 | p[n -
								2] << 8 |
			    p[n - 1];
		} else if (pk->version == 4) {
			cdk_pk_get_fingerprint(pk, buf);
			pk->keyid[0] = _cdk_buftou32(buf + 12);
			pk->keyid[1] = _cdk_buftou32(buf + 16);
		}
	}
	lowbits = pk ? pk->keyid[1] : 0;
	if (keyid && pk) {
		keyid[0] = pk->keyid[0];
		keyid[1] = pk->keyid[1];
	}

	return lowbits;
}
Exemple #5
0
static cdk_error_t
parse_sig_subpackets (cdk_pkt_signature_t sig)
{
  cdk_subpkt_t node;

  /* Setup the standard packet entries, so we can use V4
     signatures similar to V3. */
  for (node = sig->unhashed; node; node = node->next)
    {
      if (node->type == CDK_SIGSUBPKT_ISSUER && node->size >= 8)
	{
	  sig->keyid[0] = _cdk_buftou32 (node->d);
	  sig->keyid[1] = _cdk_buftou32 (node->d + 4);
	}
      else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0)
	{
	  /* Sometimes this packet might be placed in the unhashed area */
	  sig->flags.exportable = 0;
	}
    }
  for (node = sig->hashed; node; node = node->next)
    {
      if (node->type == CDK_SIGSUBPKT_SIG_CREATED && node->size >= 4)
	sig->timestamp = _cdk_buftou32 (node->d);
      else if (node->type == CDK_SIGSUBPKT_SIG_EXPIRE && node->size >= 4)
	{
	  sig->expiredate = _cdk_buftou32 (node->d);
	  if (sig->expiredate > 0 && sig->expiredate < (u32) time (NULL))
	    sig->flags.expired = 1;
	}
      else if (node->type == CDK_SIGSUBPKT_POLICY)
	sig->flags.policy_url = 1;
      else if (node->type == CDK_SIGSUBPKT_NOTATION)
	sig->flags.notation = 1;
      else if (node->type == CDK_SIGSUBPKT_REVOCABLE && node->d[0] == 0)
	sig->flags.revocable = 0;
      else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0)
	sig->flags.exportable = 0;
    }
  if (sig->sig_class == 0x1F)
    {
      cdk_desig_revoker_t r, rnode;

      for (node = sig->hashed; node; node = node->next)
	{
	  if (node->type == CDK_SIGSUBPKT_REV_KEY)
	    {
	      if (node->size < 22)
		continue;
	      rnode = cdk_calloc (1, sizeof *rnode);
	      if (!rnode)
		return CDK_Out_Of_Core;
	      rnode->r_class = node->d[0];
	      rnode->algid = node->d[1];
	      memcpy (rnode->fpr, node->d + 2, KEY_FPR_LEN);
	      if (!sig->revkeys)
		sig->revkeys = rnode;
	      else
		{
		  for (r = sig->revkeys; r->next; r = r->next)
		    ;
		  r->next = rnode;
		}
	    }
	}
    }

  return 0;
}
Exemple #6
0
static cdk_error_t
read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr)
{
  const byte *p;
  byte *buf;
  size_t len, nread;
  cdk_error_t rc;

  if (!inp || !attr || !pktlen)
    return CDK_Inv_Value;

  if (DEBUG_PKT)
    _cdk_log_debug ("read_attribute: %d octets\n", pktlen);

  strcpy (attr->name, "[attribute]");
  attr->len = strlen (attr->name);
  buf = cdk_calloc (1, pktlen);
  if (!buf)
    return CDK_Out_Of_Core;
  rc = stream_read (inp, buf, pktlen, &nread);
  if (rc)
    {
      cdk_free (buf);
      return CDK_Inv_Packet;
    }
  p = buf;
  len = *p++;
  pktlen--;
  if (len == 255)
    {
      len = _cdk_buftou32 (p);
      p += 4;
      pktlen -= 4;
    }
  else if (len >= 192)
    {
      if (pktlen < 2)
	{
	  cdk_free (buf);
	  return CDK_Inv_Packet;
	}
      len = ((len - 192) << 8) + *p + 192;
      p++;
      pktlen--;
    }

  if (*p != 1)			/* Currently only 1, meaning an image, is defined. */
    {
      cdk_free (buf);
      return CDK_Inv_Packet;
    }
  p++;
  len--;

  if (pktlen - (len + 1) > 0)
    return CDK_Inv_Packet;
  attr->attrib_img = cdk_calloc (1, len);
  if (!attr->attrib_img)
    {
      cdk_free (buf);
      return CDK_Out_Of_Core;
    }
  attr->attrib_len = len;
  memcpy (attr->attrib_img, p, len);
  cdk_free (buf);
  return rc;
}
Exemple #7
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;
}
Exemple #8
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;
}