[PATCH] PKCS#5 PBKDF2

Simon Josefsson jas@extundo.com
Tue, 03 Dec 2002 22:41:33 +0100


Werner Koch <wk@gnupg.org> writes:

> On Tue, 03 Dec 2002 02:53:07 +0100, Simon Josefsson said:
>
>> Not sure if this is suitable for libgcrypt, but it seems that even a
>> complete PKCS#5 implementation would be so small it doesn't make sense
>> to create a libpkcs5.  Only tested on alphaev68-dec-osf5.1 and
>> i686-pc-linux-gnu.
>
> I think that key derive functions make sense in libgcrypt becuase they
> are basic crypto building blocks.  However we should not add just
> pkcs5 but introduce a generic key derive API much like we have it for
> the other building blocks.  Would you like to work on it?  

Yes, although it won't be main priority.  I guess the most important
thing is to define how the API would look like.  I haven't thought
about what properties a generic key derivation algorithm has, so here
is a starting point that can be modified by someone who thought about
it (I might get around to thinking about it too, of course..).

/* Algorithm IDs for the key derivation functions we know about. Not all of them
   are implemented. */
enum gcry_kd_algos
  {
    GCRY_KD_NONE           = 0,
    GCRY_KD_PKCS5_PBKDF    = 1,
    GCRY_KD_PKCS5_PBKDF2   = 2,
    GCRY_KD_RFC2440_SIMPLE = 3,
    GCRY_KD_RFC2440_SALTED = 4,
    GCRY_KD_RFC2440_ITERSALTED = 5
  };

/* Flags used with the gcry_kd_open function. */
enum gcry_kd_flags
  {
    GCRY_KD_FLAG_SECURE = 1,  /* Allocate all buffers in "secure" memory */
  };


/* This object is used to hold a handle to an key derivation object. */
struct gcry_kd_context;
struct gcry_kd_handle
  { ...
  };
typedef struct gcry_kd_handle *Gcry_KD_Hd;

/* Create a key derivation object for algorithm ALGO.  FLAGS may be
   given as an bitwise OR of the gcry_kd_flags values. */
Gcry_KD_Hd gcry_kd_open(int algo, unsigned int flags);

/* Release the message digest object HD. */
void gcry_kd_close (Gcry_KD_Hd hd);

/* Create a new key derivation object as an exact copy of the object HD. */
Gcry_Kd_Hd gcry_kd_copy (Gcry_KD_Hd hd);

/* Reset the key derivation object HD to its initail state. */
void gcry_kd_reset (Gcry_KD_Hd hd);

/* Perform various operations on the key derivation object HD. */
int gcry_kd_ctl (Gcry_KD_Hd hd, int cmd, unsigned char *buffer, size_t buflen);

/* Read out the final key from HD.  If algorithm uses a fixed size
   output, length can be 0. */
unsigned char *gcry_kd_read (Gcry_KD_Hd hd, size_t length);

/* Retrieve the algorithm used with HD. */
int gcry_kd_get_algo (Gcry_KD_Hd hd);

/* Retrieved the length in bytes of the key yielded by algorithm
   ALGO. This is 0 if the output length is decided by user. */
unsigned int gcry_kd_get_algo_dlen (int algo);

/* Map the key derivation algorithm id ALGO to a string representation of the
   algorithm name.  For unknown algorithms this functions returns an
   empty string. */
const char *gcry_kd_algo_name (int algo);

/* Map the algorithm NAME to a key derivation algorithm Id.  Return 0 if
   the algorithm name is not known. */
int gcry_kd_map_name (const char* name);

/* Set string to derive key from. */
#define gcry_kd_set_password(hd, str, len) \
	    gcry_kd_ctl( (a), GCRYCTL_SET_PASSWORD, str, len )

/* Set salt to derive key from. */
#define gcry_kd_set_salt(hd, str, len) \
	    gcry_kd_ctl( (a), GCRYCTL_SET_SALT, str, len )

/* Set iteration count for key derivation (currently only used by PKCS5 KD's. */
#define gcry_kd_set_salt(hd, i) \
	    gcry_kd_ctl( (a), GCRYCTL_SET_ITERATION, i, NULL )

/* Set hash algorithm for key derivation (currently only used by PKCS5 KD's. */
#define gcry_kd_set_hash(hd, algo) \
	    gcry_kd_ctl( (a), GCRYCTL_SET_HASH, algo, NULL )

>> On a similar topic, what do you think about adding a CRC32 "message
>> digest"?  It might be useful to have, even though it is not the most
>> secure message digest, and the libgcrypt framework fits rather nicely.
>
> Doing CRC32 is pretty easy to code, so there is no real advantage.
> OTOH, I agree that it fits perfectly into the message digest framework
> and it is useful for certain applications.  I don't know of any OIDs
> assigned to CRC algorithms, so I can assign this one from the GNU arc:
>
> /* GNU.crcAlgorithm.crc32 */
> "1.3.6.1.4.1.11591.14.1"
>
> Please tell if if you want to use it.

I don't need any OID, but if a CRC-32 MD algo is included I guess it
makes sense to allocate one.  Is it possible to map an OID to an algo
and certain flags?  If so, and if possible, maybe allocating another
OID for the modified CRC-32 algorithm as defined by RFC 1510bis would
be useful too.  I'm thinking of having a CRC-32 gcrypt MD algo, and
the RFC1510 variation as a gcrypt MD flag.