/** @param hash The index of the hash desired @param fname The name of the file you wish to hash @param out [out] The destination of the digest @param outlen [in/out] The max size and resulting size of the message digest @result CRYPT_OK if successful */ int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE return CRYPT_NOP; #else FILE *in; int err; LTC_ARGCHK(fname != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } err = fopen_s(&in, fname, "rb"); if (err != 0) { return CRYPT_FILE_NOTFOUND; } err = hash_filehandle(hash, in, out, outlen); if (fclose(in) != 0) { return CRYPT_ERROR; } return err; #endif }
/* all in one step */ int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen) { unsigned long hashsize; int err; unsigned char *extracted; /* make sure hash descriptor is valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hashsize = hash_descriptor[hash_idx].hashsize; extracted = XMALLOC(hashsize); /* replace with static buffer? */ if (extracted == NULL) { return CRYPT_MEM; } if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) { zeromem(extracted, hashsize); XFREE(extracted); return err; } err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen); zeromem(extracted, hashsize); XFREE(extracted); return err; }
/** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { hash_state md; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(prng != NULL); if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { return err; } /* start the hash */ if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) { return err; } /* hash the current pool */ if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) { return err; } /* add the new entropy */ if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { return err; } /* store result */ if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) { return err; } return CRYPT_OK; }
/** Terminate an HMAC session @param hmac The HMAC state @param out [out] The destination of the HMAC authentication tag @param outlen [in/out] The max size and resulting size of the HMAC authentication tag @return CRYPT_OK if successful */ int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) { unsigned char buf[MAXBLOCKSIZE], isha[MAXBLOCKSIZE]; unsigned long hashsize, i; int hash, err; LTC_ARGCHK(hmac != NULL); LTC_ARGCHK(out != NULL); /* test hash */ hash = hmac->hash; if((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } /* get the hash message digest size */ hashsize = hash_descriptor[hash].hashsize; /* Get the hash of the first HMAC vector plus the data */ if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { goto LBL_ERR; } /* Create the second HMAC vector vector for step (3) */ for(i=0; i < HMAC_BLOCKSIZE; i++) { buf[i] = hmac->key[i] ^ 0x5C; } /* Now calculate the "outer" hash for step (5), (6), and (7) */ if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) { goto LBL_ERR; } /* copy to output */ for (i = 0; i < hashsize && i < *outlen; i++) { out[i] = buf[i]; } *outlen = i; err = CRYPT_OK; LBL_ERR: XFREE(hmac->key); #ifdef LTC_CLEAN_STACK zeromem(isha, hashsize); zeromem(buf, hashsize); zeromem(hmac, sizeof(*hmac)); #endif return err; }
/** HMAC a file @param hash The index of the hash you wish to use @param fname The name of the file you wish to HMAC @param key The secret key @param keylen The length of the secret key @param out [out] The HMAC authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int hmac_file(int hash, const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE return CRYPT_NOP; #else hmac_state hmac; FILE *in; unsigned char buf[512]; size_t x; int err; LTC_ARGCHK(fname != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { return err; } in = fopen(fname, "rb"); if (in == NULL) { return CRYPT_FILE_NOTFOUND; } /* process the file contents */ do { x = fread(buf, 1, sizeof(buf), in); if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { /* we don't trap this error since we're already returning an error! */ fclose(in); return err; } } while (x == sizeof(buf)); if (fclose(in) != 0) { return CRYPT_ERROR; } /* get final hmac */ if ((err = hmac_done(&hmac, out, outlen)) != CRYPT_OK) { return err; } #ifdef LTC_CLEAN_STACK /* clear memory */ zeromem(buf, sizeof(buf)); #endif return CRYPT_OK; #endif }
/** Hash multiple (non-adjacent) blocks of memory at once. @param hash The index of the hash you wish to use @param out [out] Where to store the digest @param outlen [in/out] Max size and resulting size of the digest @param in The data you wish to hash @param inlen The length of the data to hash (octets) @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { hash_state *md; int err; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (*outlen < hash_descriptor[hash].hashsize) { *outlen = hash_descriptor[hash].hashsize; return CRYPT_BUFFER_OVERFLOW; } md = XMALLOC(sizeof(hash_state)); if (md == NULL) { return CRYPT_MEM; } if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = hash_descriptor[hash].process(md, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } err = hash_descriptor[hash].done(md, out); *outlen = hash_descriptor[hash].hashsize; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif XFREE(md); va_end(args); return err; }
/** Process data through HMAC @param hmac The hmac state @param in The data to send through HMAC @param inlen The length of the data to HMAC (octets) @return CRYPT_OK if successful */ int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) { int err; LTC_ARGCHK(hmac != NULL); LTC_ARGCHK(in != NULL); if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { return err; } return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen); }
/** HMAC a block of memory to produce the authentication tag @param hash The index of the hash to use @param key The secret key @param keylen The length of the secret key (octets) @param in The data to HMAC @param inlen The length of the data to HMAC (octets) @param out [out] Destination of the authentication tag @param outlen [in/out] Max size and resulting size of authentication tag @return CRYPT_OK if successful */ int hmac_memory(int hash, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { hmac_state *hmac; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* make sure hash descriptor is valid */ if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } /* is there a descriptor? */ if (hash_descriptor[hash].hmac_block != NULL) { return hash_descriptor[hash].hmac_block(key, keylen, in, inlen, out, outlen); } /* nope, so call the hmac functions */ /* allocate ram for hmac state */ hmac = XMALLOC(sizeof(hmac_state)); if (hmac == NULL) { return CRYPT_MEM; } if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(hmac, sizeof(hmac_state)); #endif XFREE(hmac); return err; }
/** (PKCS #1 v2.0) decrypt then OAEP depad @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @param outlen [in/out] The max size and resulting size of the plaintext (octets) @param lparam The system "lparam" value @param lparamlen The length of the lparam value (octets) @param hash_idx The index of the hash desired @param stat [out] Result of the decryption, 1==valid, 0==invalid @param key The corresponding private RSA key @return CRYPT_OK if succcessul (even if invalid) */ int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, int hash_idx, int *stat, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmp; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(stat != NULL); /* default to invalid */ *stat = 0; /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get modulus len in bits */ modulus_bitlen = mp_count_bits( (key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size( (key->N)); if (modulus_bytelen != inlen) { return CRYPT_INVALID_PACKET; } /* allocate ram */ tmp = XMALLOC(inlen); if (tmp == NULL) { return CRYPT_MEM; } /* rsa decode the packet */ x = inlen; if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) { XFREE(tmp); return err; } /* now OAEP decode the packet */ err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx, out, outlen, stat); XFREE(tmp); return err; }
Bool hash_has_entry(const Hash* hash, const Tuple* tuple) { unsigned int hcode = tuple_hash(tuple) % hash->size; HElem* he; assert(hash_is_valid(hash)); assert(tuple_is_valid(tuple)); for(he = hash->bucket[hcode]; he != NULL; he = he->next) if (!entry_cmp(he->value.entry, tuple)) break; return he != NULL; }
Bool hash_has_numb(const Hash* hash, const Numb* numb) { unsigned int hcode = numb_hash(numb) % hash->size; HElem* he; assert(hash_is_valid(hash)); assert(numb_is_valid(numb)); for(he = hash->bucket[hcode]; he != NULL; he = he->next) if (numb_equal(he->value.numb, numb)) break; return he != NULL; }
int pkcs_1_pss_test(void) { struct ltc_prng_descriptor* no_prng_desc = no_prng_desc_get(); int prng_idx = register_prng(no_prng_desc); int hash_idx = find_hash("sha1"); unsigned int i; unsigned int j; DO(prng_is_valid(prng_idx)); DO(hash_is_valid(hash_idx)); for (i = 0; i < sizeof(testcases_pss)/sizeof(testcases_pss[0]); ++i) { testcase_t* t = &testcases_pss[i]; rsa_key k, *key = &k; DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name); DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name); DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name); DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name); DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name); DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name); key->type = PK_PRIVATE; for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) { rsaData_t* s = &t->data[j]; unsigned char buf[20], obuf[256]; unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); int stat; prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (prng_state*)no_prng_desc); DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name); DOX(rsa_sign_hash(buf, buflen, obuf, &obuflen, (prng_state*)no_prng_desc, prng_idx, hash_idx, s->o2_l, key), s->name); DOX(obuflen == (unsigned long)s->o3_l?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); DOX(memcmp(s->o3, obuf, s->o3_l)==0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); DOX(rsa_verify_hash(obuf, obuflen, buf, buflen, hash_idx, s->o2_l, &stat, key), s->name); DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); } /* for */ mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); } /* for */ unregister_prng(no_prng_desc); no_prng_desc_free(no_prng_desc); return 0; }
/** (PKCS #1, v2.0) de-sign then PSS depad @param sig The signature data @param siglen The length of the signature data (octets) @param hash The hash of the message that was signed @param hashlen The length of the hash of the message that was signed (octets) @param hash_idx The index of the desired hash @param saltlen The length of the salt used during signature @param stat [out] The result of the signature comparison, 1==valid, 0==invalid @param key The public RSA key corresponding to the key that performed the signature @return CRYPT_OK on success (even if the signature is invalid) */ int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int hash_idx, unsigned long saltlen, int *stat, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmpbuf; LTC_ARGCHK(hash != NULL); LTC_ARGCHK(sig != NULL); LTC_ARGCHK(stat != NULL); LTC_ARGCHK(key != NULL); /* default to invalid */ *stat = 0; /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get modulus len in bits */ modulus_bitlen = mp_count_bits(&(key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size(&(key->N)); if (modulus_bytelen != siglen) { return CRYPT_INVALID_PACKET; } /* allocate temp buffer for decoded sig */ tmpbuf = XMALLOC(siglen); if (tmpbuf == NULL) { return CRYPT_MEM; } /* RSA decode it */ x = siglen; if ((err = rsa_exptmod(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { XFREE(tmpbuf); return err; } /* PSS decode it */ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); XFREE(tmpbuf); return err; }
/** (LTC_PKCS #1 v2.0) OAEP pad then encrypt @param in The plaintext @param inlen The length of the plaintext (octets) @param out [out] The ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param lparam The system "lparam" for the encryption @param lparamlen The length of lparam (octets) @param prng An active PRNG @param prng_idx The index of the desired prng @param hash_idx The index of the desired hash @param key The Katja key to encrypt to @return CRYPT_OK if successful */ int katja_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, prng_state *prng, int prng_idx, int hash_idx, katja_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* valid prng and hash ? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get modulus len in bits */ modulus_bitlen = mp_count_bits((key->N)); /* payload is upto pq, so we know q is 1/3rd the size of N and therefore pq is 2/3th the size */ modulus_bitlen = ((modulus_bitlen << 1) / 3); /* round down to next byte */ modulus_bitlen -= (modulus_bitlen & 7) + 8; /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen > *outlen) { *outlen = modulus_bytelen; return CRYPT_BUFFER_OVERFLOW; } /* OAEP pad the key */ x = *outlen; if ((err = pkcs_1_oaep_encode(in, inlen, lparam, lparamlen, modulus_bitlen, prng, prng_idx, hash_idx, out, &x)) != CRYPT_OK) { return err; } /* Katja exptmod the OAEP pad */ return katja_exptmod(out, x, out, outlen, PK_PUBLIC, key); }
void hash_add_numb(Hash* hash, const Numb* numb) { HElem* he = blk_alloc(sizeof(*he)); unsigned int hcode; assert(hash_is_valid(hash)); assert(numb_is_valid(numb)); assert(hash->type == HASH_NUMB); assert(he != NULL); hcode = numb_hash(numb) % hash->size; he->value.numb = numb; he->next = hash->bucket[hcode]; hash->bucket[hcode] = he; hash->elems++; }
void hash_add_mono(Hash* hash, const Mono* mono) { HElem* he = blk_alloc(sizeof(*he)); unsigned int hcode; assert(hash_is_valid(hash)); assert(mono_is_valid(mono)); assert(hash->type == HASH_MONO); assert(he != NULL); hcode = mono_hash(mono) % hash->size; he->value.mono = mono; he->next = hash->bucket[hcode]; hash->bucket[hcode] = he; hash->elems++; }
void hash_add_tuple(Hash* hash, const Tuple* tuple) { HElem* he = blk_alloc(sizeof(*he)); unsigned int hcode; assert(hash_is_valid(hash)); assert(tuple_is_valid(tuple)); assert(hash->type == HASH_TUPLE); assert(he != NULL); hcode = tuple_hash(tuple) % hash->size; he->value.tuple = tuple; he->next = hash->bucket[hcode]; hash->bucket[hcode] = he; hash->elems++; }
void hash_add_elem_idx(Hash* hash, const Elem* elem, int idx) { HElem* he = blk_alloc(sizeof(*he)); unsigned int hcode; assert(hash_is_valid(hash)); assert(elem_is_valid(elem)); assert(he != NULL); hcode = elem_hash(elem) % hash->size; he->value.elem_idx.elem = elem; he->value.elem_idx.idx = idx; he->next = hash->bucket[hcode]; hash->bucket[hcode] = he; hash->elems++; }
int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen) { unsigned char buf[MAXBLOCKSIZE]; unsigned char isha[MAXBLOCKSIZE]; unsigned long hashsize, i; int hash, err; _ARGCHK(hmac != NULL); _ARGCHK(hashOut != NULL); hash = hmac->hash; if((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } /* get the hash message digest size */ hashsize = hash_descriptor[hash].hashsize; // Get the hash of the first HMAC vector plus the data if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { return err; } // Create the second HMAC vector vector for step (3) for(i=0; i < HMAC_BLOCKSIZE; i++) { buf[i] = hmac->key[i] ^ 0x5C; } // Now calculate the "outer" hash for step (5), (6), and (7) hash_descriptor[hash].init(&hmac->md); hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE); hash_descriptor[hash].process(&hmac->md, isha, hashsize); hash_descriptor[hash].done(&hmac->md, buf); // copy to output for (i = 0; i < hashsize && i < *outlen; i++) { hashOut[i] = buf[i]; } *outlen = i; #ifdef CLEAN_STACK zeromem(isha, sizeof(buf)); zeromem(buf, sizeof(isha)); zeromem(hmac, sizeof(*hmac)); #endif return CRYPT_OK; }
/** Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature. @param padding Type of padding (LTC_PKCS_1_PSS only) @param hash_idx The index of the desired hash @param key The RSA key @return The maximum salt length in bytes or INT_MAX on error. */ int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, rsa_key *key) { int ret = INT_MAX; LTC_ARGCHK(key != NULL); if ((hash_is_valid(hash_idx) == CRYPT_OK) && (padding == LTC_PKCS_1_PSS)) { ret = rsa_get_size(key); if (ret < INT_MAX) { ret -= (hash_descriptor[hash_idx].hashsize + 2); } /* if */ } /* if */ return ret; }
int pkcs_1_eme_test(void) { int prng_idx = register_prng(&no_prng_desc); int hash_idx = find_hash("sha1"); unsigned int i; DO(prng_is_valid(prng_idx)); DO(hash_is_valid(hash_idx)); for (i = 0; i < sizeof(testcases_eme)/sizeof(testcases_eme[0]); ++i) { testcase_t* t = &testcases_eme[i]; rsa_key k, *key = &k; DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name); DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name); DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name); DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name); DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name); DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name); key->type = PK_PRIVATE; unsigned int j; for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) { rsaData_t* s = &t->data[j]; unsigned char buf[256], obuf[256]; unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); int stat; prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, NULL); DOX(rsa_encrypt_key_ex(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, NULL, prng_idx, -1, LTC_PKCS_1_V1_5, key), s->name); DOX(obuflen == (unsigned long)s->o3_l?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); DOX(memcmp(s->o3, obuf, s->o3_l)==0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, LTC_PKCS_1_V1_5, &stat, key), s->name); DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); } /* for */ mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); } /* for */ unregister_prng(&no_prng_desc); return 0; }
static cf_rv_t _digest_list_next(cf_provider_t provider, void **iter, struct cf_digest_info *info) { int *id = (int*)iter; while(*id < TAB_SIZE) { const struct ltc_hash_descriptor *hash; if (CRYPT_OK != hash_is_valid(*id)) { ++*id; continue; } hash = &hash_descriptor[*id]; info->id = *id; info->name = hash->name;; info->block_size = hash->hashsize; ++*id; return CF_S_OK; } return CF_S_COMPLETE; }
static cf_rv_t _digest_init(cf_digest_t *digest, cf_provider_t provider, cf_digest_id_t id) { struct _tomcrypt_digest *impl; if (CRYPT_OK != hash_is_valid(id)) { return CF_E_UNKNOWN; } impl = create_tomcrypt_digest_impl(); if (!impl) { return CF_E_MEM; } impl->descriptor = &hash_descriptor[id]; if (CRYPT_OK != hash_descriptor[id].init(&impl->state)) { free(impl); return CF_E_UNKNOWN; } *digest = (cf_digest_t)impl; return CF_S_OK; }
void hash_add_entry(Hash* hash, const Entry* entry) { HElem* he = blk_alloc(sizeof(*he)); const Tuple* tuple; unsigned int hcode; assert(hash_is_valid(hash)); assert(entry_is_valid(entry)); assert(hash->type == HASH_ENTRY); assert(he != NULL); tuple = entry_get_tuple(entry); hcode = tuple_hash(tuple) % hash->size; he->value.entry = entry; he->next = hash->bucket[hcode]; hash->bucket[hcode] = he; hash->elems++; }
/* Liefert -1 wenn nicht gefunden. */ int hash_lookup_elem_idx(const Hash* hash, const Elem* elem) { unsigned int hcode = elem_hash(elem) % hash->size; HElem* he; assert(hash_is_valid(hash)); assert(elem_is_valid(elem)); for(he = hash->bucket[hcode]; he != NULL; he = he->next) if (!elem_cmp(he->value.elem_idx.elem, elem)) break; if (he == NULL) return -1; assert(he != NULL); return he->value.elem_idx.idx; }
static void hash_statist(FILE* fp, const Hash* hash) { HElem* he; int min = (int)hash->size; int max = 0; int sum = 0; int zeros = 0; int filled = 0; int count; double avg = 0.0; unsigned int i; assert(fp != NULL); assert(hash_is_valid(hash)); for(i = 0; i < hash->size; i++) { count = 0; for(he = hash->bucket[i]; he != NULL; he = he->next) count++; if (count == 0) zeros++; else filled++; if (count < min) min = count; if (count > max) max = count; sum += count; } assert(sum == hash->elems); if (filled > 0) avg = (double)sum / (double)filled; fprintf(fp, "HashStat: size=%u sum=%d min=%d max=%d avg=%.1f zero=%d filled=%d\n", hash->size, sum, min, max, avg, zeros, filled); }
int pkcs_1_emsa_test(void) { int hash_idx = find_hash("sha1"); unsigned int i; unsigned int j; DO(hash_is_valid(hash_idx)); for (i = 0; i < sizeof(testcases_emsa)/sizeof(testcases_emsa[0]); ++i) { testcase_t* t = &testcases_emsa[i]; rsa_key k, *key = &k; DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name); DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name); DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name); DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name); DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name); DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name); key->type = PK_PRIVATE; for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) { rsaData_t* s = &t->data[j]; unsigned char buf[20], obuf[256]; unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); int stat; DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name); DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, 0, key), s->name); DOX(obuflen == (unsigned long)s->o2_l?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); DOX(memcmp(s->o2, obuf, s->o2_l)==0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, 0, &stat, key), s->name); DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); } /* for */ mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); } /* for */ return 0; }
/** (PKCS #1 v2.0) OAEP pad then encrypt @param in The plaintext @param inlen The length of the plaintext (octets) @param out [out] The ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param lparam The system "lparam" for the encryption @param lparamlen The length of lparam (octets) @param prng An active PRNG @param prng_idx The index of the desired prng @param hash_idx The index of the desired hash @param key The RSA key to encrypt to @return CRYPT_OK if successful */ int rsa_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, prng_state *prng, int prng_idx, int hash_idx, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* valid prng and hash ? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get modulus len in bits */ modulus_bitlen = mp_count_bits(&(key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size(&(key->N)); if (modulus_bytelen > *outlen) { return CRYPT_BUFFER_OVERFLOW; } /* OAEP pad the key */ x = *outlen; if ((err = pkcs_1_oaep_encode(in, inlen, lparam, lparamlen, modulus_bitlen, prng, prng_idx, hash_idx, out, &x)) != CRYPT_OK) { return err; } /* rsa exptmod the OAEP pad */ return rsa_exptmod(out, x, out, outlen, PK_PUBLIC, key); }
/** Hash data from an open file handle. @param hash The index of the hash you want to use @param in The FILE* handle of the file you want to hash @param out [out] The destination of the digest @param outlen [in/out] The max size and resulting size of the digest @result CRYPT_OK if successful */ int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE return CRYPT_NOP; #else hash_state md; unsigned char buf[512]; size_t x; int err; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(in != NULL); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (*outlen < hash_descriptor[hash].hashsize) { *outlen = hash_descriptor[hash].hashsize; return CRYPT_BUFFER_OVERFLOW; } if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) { return err; } *outlen = hash_descriptor[hash].hashsize; do { x = fread(buf, 1, sizeof(buf), in); if ((err = hash_descriptor[hash].process(&md, buf, x)) != CRYPT_OK) { return err; } } while (x == sizeof(buf)); err = hash_descriptor[hash].done(&md, out); #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return err; #endif }
/** (PKCS #1, v2.0) PSS pad then sign @param in The hash to sign @param inlen The length of the hash to sign (octets) @param out [out] The signature @param outlen [in/out] The max size and resulting size of the signature @param prng An active PRNG state @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @param saltlen The length of the salt desired (octets) @param key The private RSA key to use @return CRYPT_OK if successful */ int rsa_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int prng_idx, int hash_idx, unsigned long saltlen, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* valid prng and hash ? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get modulus len in bits */ modulus_bitlen = mp_count_bits(&(key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size(&(key->N)); if (modulus_bytelen > *outlen) { return CRYPT_BUFFER_OVERFLOW; } /* PSS pad the key */ x = *outlen; if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { return err; } /* RSA encode it */ return rsa_exptmod(out, x, out, outlen, PK_PRIVATE, key); }