Пример #1
0
void
cdk_keygen_set_passphrase( cdk_keygen_ctx_t hd, const char * pass )
{
    if( !hd )
        return;
    if( pass ) {
        size_t n = strlen( pass );
        _cdk_sec_free( hd->pass, hd->pass_len );
        hd->pass = cdk_salloc( n + 1, 1 );
        if( hd->pass ) {
            memcpy( hd->pass, pass, n );
            hd->pass[n] = '\0';
            hd->pass_len = n;
            hd->protect = 1;
        }
    }
}
Пример #2
0
static int
gcry_mpi_to_native( cdk_keygen_ctx_t hd, size_t nkey, int type,
                    cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk )
{
    gcry_mpi_t * resarr;
    cdk_mpi_t a = NULL;
    size_t nbytes;
    int i = 0, j = 0, nbits;
    int rc = 0;

    if( !hd )
        return CDK_Inv_Value;
    if( !pk && !sk )
        return CDK_Inv_Value;
    if( type < 0 || type > 1 )
        return CDK_Inv_Value;

    resarr = hd->key[type].resarr;
    if( sk )
        i += cdk_pk_get_npkey( sk->pubkey_algo );
    while( j != nkey ) {
        nbits = gcry_mpi_get_nbits( resarr[i] );
        if( pk )
            a = cdk_calloc( 1, sizeof * a + (nbits + 7) / 8 + 2 + 1 );
        else if( sk )
            a = cdk_salloc( sizeof * a + (nbits + 7) / 8 + 2 + 1, 1 );
        a->bits = nbits;
        a->bytes = ( nbits + 7 ) / 8;
        nbytes = a->bytes;
        a->data[0] = nbits >> 8;
        a->data[1] = nbits;
        rc = gcry_mpi_print( GCRYMPI_FMT_USG, a->data+2, nbytes, &nbytes, resarr[i] );
        if( rc )
            break;
        if( pk )
            pk->mpi[j++] = a;
        else if( sk )
            sk->mpi[j++] = a;
        i++;
    }
    return rc;
}
Пример #3
0
/**
 * cdk_sk_unprotect:
 * @sk: the secret key
 * @pw: the passphrase
 * 
 * Unprotect the given secret key with the passphrase.
 **/
cdk_error_t
cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw)
{
  gcry_cipher_hd_t hd;
  cdk_dek_t dek = NULL;
  byte *data = NULL;
  u16 chksum = 0;
  size_t ndata, nbits, nbytes;
  int i, dlen, pos = 0, nskey;
  cdk_error_t rc;
  gcry_error_t err;
  
  if (!sk)
    return CDK_Inv_Value;
  
  nskey = cdk_pk_get_nskey (sk->pubkey_algo);
  if (!sk->is_protected)
    {
      chksum = 0;
      for (i = 0; i < nskey; i++)
	chksum += checksum_mpi (sk->mpi[i]);
      if (chksum != sk->csum)
	return CDK_Chksum_Error;
    } 
      
  rc = cdk_dek_from_passphrase (&dek, sk->protect.algo,
				sk->protect.s2k, 0, pw);
  if (rc)
    return rc;
  err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, 
			  GCRY_CIPHER_ENABLE_SYNC);
  if (!err)
    err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
  if (!err)
    err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
  if (err)
    {
      cdk_free (dek);
      return map_gcry_error (err);
    }
  cdk_dek_free (dek);
  chksum = 0;
  if (sk->version == 4) 
    {
      ndata = sk->enclen;
      data = cdk_salloc (ndata, 1);
      if (!data)
	return CDK_Out_Of_Core;
      gcry_cipher_decrypt (hd, data, ndata, sk->encdata, ndata);
      if (sk->protect.sha1chk) 
	{
	  /* This is the new SHA1 checksum method to detect tampering
	     with the key as used by the Klima/Rosa attack */
	  sk->csum = 0;
	  chksum = 1;
	  dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
	  if (ndata < dlen) 
	    {
	      cdk_free (data);
	      return CDK_Inv_Packet;
	    }
	  else 
	    {
	      byte mdcheck[20];
	      
	      gcry_md_hash_buffer (GCRY_MD_SHA1, 
				   mdcheck, data, ndata-dlen);
	      if (!memcmp (mdcheck, data + ndata - dlen, dlen))
		chksum = 0;	/* Digest does match */
	    }
	}
      else 
	{
	  for (i = 0; i < ndata - 2; i++)
	    chksum += data[i];
	  sk->csum = data[ndata - 2] << 8 | data[ndata - 1];
	}
      if (sk->csum == chksum) 
	{
	  for (i = 0; i < nskey; i++) 
	    {
	      nbits = data[pos] << 8 | data[pos + 1];
	      
	      if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, data,
			     (nbits+7)/8+2, &nbytes))
		{
		  wipemem (data, sk->enclen);
		  cdk_free (data);
		  return CDK_Wrong_Format;
		}	     
	      gcry_mpi_set_flag (sk->mpi[i], GCRYMPI_FLAG_SECURE);
	      pos += (nbits+7)/8+2;
	    }
	}
      wipemem (data, sk->enclen);
      cdk_free (data);
    }
  else 
    {
      byte buf[MAX_MPI_BYTES+2];
      
      chksum = 0;
      for (i = 0; i < nskey; i++)
	{
	  gcry_cipher_sync (hd);
	  gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), 
			  &nbytes, sk->mpi[i]);
	  gcry_cipher_decrypt (hd, buf+2, nbytes-2, NULL, 0);
	  gcry_mpi_release (sk->mpi[i]);
	  if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP,
			     buf, nbytes, &nbytes))
	    return CDK_Wrong_Format;
	  chksum += checksum_mpi (sk->mpi[i]);
	}
    }
  gcry_cipher_close (hd);
  if (chksum != sk->csum)
    return CDK_Chksum_Error;
  sk->is_protected = 0;
  return 0;
}