1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file pkcs_1_mgf1.c
7   The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis
8 */
9 
10 #ifdef LTC_PKCS_1
11 
12 /**
13    Perform PKCS #1 MGF1 (internal)
14    @param hash_idx    The index of the hash desired
15    @param seed        The seed for MGF1
16    @param seedlen     The length of the seed
17    @param mask        [out] The destination
18    @param masklen     The length of the mask desired
19    @return CRYPT_OK if successful
20 */
pkcs_1_mgf1(int hash_idx,const unsigned char * seed,unsigned long seedlen,unsigned char * mask,unsigned long masklen)21 int pkcs_1_mgf1(int                  hash_idx,
22                 const unsigned char *seed, unsigned long seedlen,
23                       unsigned char *mask, unsigned long masklen)
24 {
25    unsigned long hLen, x;
26    ulong32       counter;
27    int           err;
28    hash_state    *md;
29    unsigned char *buf;
30 
31    LTC_ARGCHK(seed != NULL);
32    LTC_ARGCHK(mask != NULL);
33 
34    /* ensure valid hash */
35    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
36       return err;
37    }
38 
39    /* get hash output size */
40    hLen = hash_descriptor[hash_idx]->hashsize;
41 
42    /* allocate memory */
43    md  = XMALLOC(sizeof(hash_state));
44    buf = XMALLOC(hLen);
45    if (md == NULL || buf == NULL) {
46       if (md != NULL) {
47          XFREE(md);
48       }
49       if (buf != NULL) {
50          XFREE(buf);
51       }
52       return CRYPT_MEM;
53    }
54 
55    /* start counter */
56    counter = 0;
57 
58    while (masklen > 0) {
59        /* handle counter */
60        STORE32H(counter, buf);
61        ++counter;
62 
63        /* get hash of seed || counter */
64        if ((err = hash_descriptor[hash_idx]->init(md)) != CRYPT_OK) {
65           goto LBL_ERR;
66        }
67        if ((err = hash_descriptor[hash_idx]->process(md, seed, seedlen)) != CRYPT_OK) {
68           goto LBL_ERR;
69        }
70        if ((err = hash_descriptor[hash_idx]->process(md, buf, 4)) != CRYPT_OK) {
71           goto LBL_ERR;
72        }
73        if ((err = hash_descriptor[hash_idx]->done(md, buf)) != CRYPT_OK) {
74           goto LBL_ERR;
75        }
76 
77        /* store it */
78        for (x = 0; x < hLen && masklen > 0; x++, masklen--) {
79           *mask++ = buf[x];
80        }
81    }
82 
83    err = CRYPT_OK;
84 LBL_ERR:
85 #ifdef LTC_CLEAN_STACK
86    zeromem(buf, hLen);
87    zeromem(md,  sizeof(hash_state));
88 #endif
89 
90    XFREE(buf);
91    XFREE(md);
92 
93    return err;
94 }
95 
96 #endif /* LTC_PKCS_1 */
97