diff src/misc/pkcs5/pkcs_5_2.c @ 191:1c15b283127b libtomcrypt-orig

Import of libtomcrypt 1.02 with manual path rename rearrangement etc
author Matt Johnston <matt@ucc.asn.au>
date Fri, 06 May 2005 13:23:02 +0000
parents
children 39d5d58461d6
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/misc/pkcs5/pkcs_5_2.c	Fri May 06 13:23:02 2005 +0000
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include <tomcrypt.h>
+
+/** 
+   @file pkcs_5_2.c
+   PKCS #5, Algorithm #2, Tom St Denis
+*/
+#ifdef PKCS_5
+
+/**
+   Execute PKCS #5 v2
+   @param password          The input password (or key)
+   @param password_len      The length of the password (octets)
+   @param salt              The salt (or nonce)
+   @param salt_len          The length of the salt (octets)
+   @param iteration_count   # of iterations desired for PKCS #5 v2 [read specs for more]
+   @param hash_idx          The index of the hash desired
+   @param out               [out] The destination for this algorithm
+   @param outlen            [in/out] The max size and resulting size of the algorithm output
+   @return CRYPT_OK if successful
+*/
+int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, 
+                const unsigned char *salt,     unsigned long salt_len,
+                int iteration_count,           int hash_idx,
+                unsigned char *out,            unsigned long *outlen)
+{
+   int err, itts;
+   ulong32  blkno;
+   unsigned long stored, left, x, y;
+   unsigned char *buf[2];
+   hmac_state    *hmac;
+
+   LTC_ARGCHK(password != NULL);
+   LTC_ARGCHK(salt     != NULL);
+   LTC_ARGCHK(out      != NULL);
+   LTC_ARGCHK(outlen   != NULL);
+
+   /* test hash IDX */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   buf[0] = XMALLOC(MAXBLOCKSIZE * 2);
+   hmac   = XMALLOC(sizeof(hmac_state));
+   if (hmac == NULL || buf[0] == NULL) {
+      if (hmac != NULL) {
+         XFREE(hmac);
+      }
+      if (buf[0] != NULL) {
+         XFREE(buf[0]);
+      }
+      return CRYPT_MEM;
+   }
+   /* buf[1] points to the second block of MAXBLOCKSIZE bytes */
+   buf[1] = buf[0] + MAXBLOCKSIZE;
+
+   left   = *outlen;
+   blkno  = 1;
+   stored = 0;
+   while (left != 0) {
+       /* process block number blkno */
+       zeromem(buf[0], MAXBLOCKSIZE*2);
+       
+       /* store current block number and increment for next pass */
+       STORE32H(blkno, buf[1]);
+       ++blkno;
+
+       /* get PRF(P, S||int(blkno)) */
+       if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { 
+          goto LBL_ERR;
+       }
+       if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) {
+          goto LBL_ERR;
+       }
+       if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) {
+          goto LBL_ERR;
+       }
+       x = MAXBLOCKSIZE;
+       if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) {
+          goto LBL_ERR;
+       }
+
+       /* now compute repeated and XOR it in buf[1] */
+       XMEMCPY(buf[1], buf[0], x);
+       for (itts = 1; itts < iteration_count; ++itts) {
+           if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) {
+              goto LBL_ERR;
+           }
+           for (y = 0; y < x; y++) {
+               buf[1][y] ^= buf[0][y];
+           }
+       }
+
+       /* now emit upto x bytes of buf[1] to output */
+       for (y = 0; y < x && left != 0; ++y) {
+           out[stored++] = buf[1][y];
+           --left;
+       }
+   }
+   *outlen = stored;
+
+   err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+   zeromem(buf[0], MAXBLOCKSIZE*2);
+   zeromem(hmac, sizeof(hmac_state));
+#endif
+
+   XFREE(hmac);
+   XFREE(buf[0]);
+
+   return err;
+}
+
+#endif
+