int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) #endif { ulong32 a,b,c,d,t,u, *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]); b += skey->rc6.K[0]; d += skey->rc6.K[1]; #define RND(a,b,c,d) \ t = (b * (b + b + 1)); t = ROLc(t, 5); \ u = (d * (d + d + 1)); u = ROLc(u, 5); \ a = ROL(a^t,u) + K[0]; \ c = ROL(c^u,t) + K[1]; K += 2; K = skey->rc6.K + 2; for (r = 0; r < 20; r += 4) { RND(a,b,c,d); RND(b,c,d,a); RND(c,d,a,b); RND(d,a,b,c); } #undef RND a += skey->rc6.K[42]; c += skey->rc6.K[43]; STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]); return CRYPT_OK; }
void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) #endif { ulong32 a,b,c,d,t,u, *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]); a -= skey->rc6.K[42]; c -= skey->rc6.K[43]; #define RND(a,b,c,d) \ t = (b * (b + b + 1)); t = ROLc(t, 5); \ u = (d * (d + d + 1)); u = ROLc(u, 5); \ c = ROR(c - K[1], t) ^ u; \ a = ROR(a - K[0], u) ^ t; K -= 2; K = skey->rc6.K + 40; for (r = 0; r < 20; r += 4) { RND(d,a,b,c); RND(c,d,a,b); RND(b,c,d,a); RND(a,b,c,d); } #undef RND b -= skey->rc6.K[0]; d -= skey->rc6.K[1]; STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]); }
int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) #endif { ulong32 A, B, *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32L(A, &pt[0]); LOAD32L(B, &pt[4]); A += skey->rc5.K[0]; B += skey->rc5.K[1]; K = skey->rc5.K + 2; if ((skey->rc5.rounds & 1) == 0) { for (r = 0; r < skey->rc5.rounds; r += 2) { A = ROL(A ^ B, B) + K[0]; B = ROL(B ^ A, A) + K[1]; A = ROL(A ^ B, B) + K[2]; B = ROL(B ^ A, A) + K[3]; K += 4; } } else { for (r = 0; r < skey->rc5.rounds; r++) { A = ROL(A ^ B, B) + K[0]; B = ROL(B ^ A, A) + K[1]; K += 2; } } STORE32L(A, &ct[0]); STORE32L(B, &ct[4]); return CRYPT_OK; }
void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) #endif { unsigned long a,b,c,d,temp; int r; _ARGCHK(key != NULL); _ARGCHK(pt != NULL); _ARGCHK(ct != NULL); LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]); LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]); #define ROUND(i) \ a ^= RC[r+i]; \ THETA(key->noekeon.K, a,b,c,d); \ PI1(a,b,c,d); \ GAMMA(a,b,c,d); \ PI2(a,b,c,d); for (r = 0; r < 16; r += 2) { ROUND(0); ROUND(1); } #undef ROUND a ^= RC[16]; THETA(key->noekeon.K, a, b, c, d); STORE32L(a,&ct[0]); STORE32L(b,&ct[4]); STORE32L(c,&ct[8]); STORE32L(d,&ct[12]); }
static void XORWORD(ulong32 w, unsigned char *b) { ulong32 t; LOAD32L(t, b); t ^= w; STORE32L(t, b); }
static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) { ulong32 t; LOAD32L(t, in); t ^= w; STORE32L(t, out); }
int blake2s_done(hash_state *md, unsigned char *out) { unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 }; unsigned long i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */ if (blake2s_is_lastblock(md)) return CRYPT_ERROR; blake2s_increment_counter(md, md->blake2s.curlen); blake2s_set_lastblock(md); XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */ blake2s_compress(md, md->blake2s.buf); for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */ STORE32L(md->blake2s.h[i], buffer + i * 4); XMEMCPY(out, buffer, md->blake2s.outlen); zeromem(md, sizeof(hash_state)); #ifdef LTC_CLEAN_STACK zeromem(buffer, sizeof(buffer)); #endif return CRYPT_OK; }
void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) #endif { unsigned long A, B; int r; _ARGCHK(key != NULL); _ARGCHK(pt != NULL); _ARGCHK(ct != NULL); LOAD32L(A, &pt[0]); LOAD32L(B, &pt[4]); A += key->rc5.K[0]; B += key->rc5.K[1]; for (r = 0; r < key->rc5.rounds; r++) { A = ROL(A ^ B, B) + key->rc5.K[r+r+2]; B = ROL(B ^ A, A) + key->rc5.K[r+r+3]; } STORE32L(A, &ct[0]); STORE32L(B, &ct[4]); }
void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) #endif { unsigned long A, B; int r; _ARGCHK(key != NULL); _ARGCHK(pt != NULL); _ARGCHK(ct != NULL); LOAD32L(A, &ct[0]); LOAD32L(B, &ct[4]); for (r = key->rc5.rounds - 1; r >= 0; r--) { B = ROR(B - key->rc5.K[r+r+3], A) ^ A; A = ROR(A - key->rc5.K[r+r+2], B) ^ B; } A -= key->rc5.K[0]; B -= key->rc5.K[1]; STORE32L(A, &pt[0]); STORE32L(B, &pt[4]); }
void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) #endif { unsigned long a,b,c,d,t,u; int r; _ARGCHK(key != NULL); _ARGCHK(pt != NULL); _ARGCHK(ct != NULL); LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]); b += key->rc6.K[0]; d += key->rc6.K[1]; for (r = 0; r < 20; r++) { t = (b * (b + b + 1)); t = ROL(t, 5); u = (d * (d + d + 1)); u = ROL(u, 5); a = ROL(a^t,u) + key->rc6.K[r+r+2]; c = ROL(c^u,t) + key->rc6.K[r+r+3]; t = a; a = b; b = c; c = d; d = t; } a += key->rc6.K[42]; c += key->rc6.K[43]; STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]); }
int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) #endif { ulong32 A, B, *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32L(A, &ct[0]); LOAD32L(B, &ct[4]); K = skey->rc5.K + (skey->rc5.rounds << 1); if ((skey->rc5.rounds & 1) == 0) { K -= 2; for (r = skey->rc5.rounds - 1; r >= 0; r -= 2) { B = ROR(B - K[3], A) ^ A; A = ROR(A - K[2], B) ^ B; B = ROR(B - K[1], A) ^ A; A = ROR(A - K[0], B) ^ B; K -= 4; } } else { for (r = skey->rc5.rounds - 1; r >= 0; r--) { B = ROR(B - K[1], A) ^ A; A = ROR(A - K[0], B) ^ B; K -= 2; } } A -= skey->rc5.K[0]; B -= skey->rc5.K[1]; STORE32L(A, &pt[0]); STORE32L(B, &pt[4]); return CRYPT_OK; }
void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) #endif { unsigned long a,b,c,d,t,u; int r; _ARGCHK(key != NULL); _ARGCHK(pt != NULL); _ARGCHK(ct != NULL); LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]); a -= key->rc6.K[42]; c -= key->rc6.K[43]; for (r = 19; r >= 0; r--) { t = d; d = c; c = b; b = a; a = t; t = (b * (b + b + 1)); t = ROL(t, 5); u = (d * (d + d + 1)); u = ROL(u, 5); c = ROR(c - key->rc6.K[r+r+3], t) ^ u; a = ROR(a - key->rc6.K[r+r+2], u) ^ t; } b -= key->rc6.K[0]; d -= key->rc6.K[1]; STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]); }
/** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (16 bytes) @return CRYPT_OK if successful */ int rmd128_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->rmd128.length += md->rmd128.curlen * 8; /* append the '1' bit */ md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->rmd128.curlen > 56) { while (md->rmd128.curlen < 64) { md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; } rmd128_compress(md, md->rmd128.buf); md->rmd128.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->rmd128.curlen < 56) { md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->rmd128.length, md->rmd128.buf+56); rmd128_compress(md, md->rmd128.buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md->rmd128.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; }
/** Terminate the hash to get the digest @param sha1 The hash state @param out [out] The destination of the hash (16 bytes) */ void md5_done(struct md5_state *md5, unsigned char *out) { int i; assert(md5 != NULL); assert(out != NULL); assert(md5->curlen < sizeof(md5->buf)); /* increase the length of the message */ md5->length += md5->curlen * 8; /* append the '1' bit */ md5->buf[md5->curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md5->curlen > 56) { while (md5->curlen < 64) { md5->buf[md5->curlen++] = (unsigned char)0; } md5_compress(md5, md5->buf); md5->curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md5->curlen < 56) { md5->buf[md5->curlen++] = (unsigned char)0; } /* store length */ STORE64L(md5->length, md5->buf+56); md5_compress(md5, md5->buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md5->state[i], out+(4*i)); } }
static void smix ( uint8_t *b, const size_t r, uint64_t n, uint32_t *t0, uint32_t *t1, uint32_t *t2 ) { uint64_t i; uint64_t tn; uint64_t j; for(i = 0; i < (r << 5); i++) t1[i] = LOAD32L(b + (i << 2)); for(i = 0; i < n; i++) { memcpy(t0 + (r << 5) * i, t1, r << 7); blockmix(t1, t2, r); } for(i = 0; i < n; i++) { /* integrify */ tn = (((uint64_t)t1[(r << 5) - 15] << 32) | t1[(r << 5) - 16]) & (n - 1); for(j = 0; j < (r << 5); j++) t1[j] ^= t0[(r << 5) * tn + j]; blockmix(t1, t2, r); } for(i = 0; i < (r << 5); i++) STORE32L(t1[i], b + (i << 2)); }
int32 psMd4Final(psDigestContext_t * md, unsigned char *out) { int32 i; #ifndef HAVE_NATIVE_INT64 uint32 n; #endif psAssert(md != NULL); psAssert(out != NULL); if (md->md4.curlen >= sizeof(md->md4.buf)) { psTraceCrypto("psMd4Final error\n"); return PS_LIMIT_FAIL; } /* increase the length of the message */ #ifdef HAVE_NATIVE_INT64 md->md4.length += md->md4.curlen << 3; #else n = (md->md4.lengthLo + (md->md4.curlen << 3)) & 0xFFFFFFFFL; if (n < md->md4.lengthLo) { md->md4.lengthHi++; } md->md4.lengthHi += (md->md4.curlen >> 29); md->md4.lengthLo = n; #endif /* HAVE_NATIVE_INT64 */ /* append the '1' bit */ md->md4.buf[md->md4.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->md4.curlen > 56) { while (md->md4.curlen < 64) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } md4_compress(md, md->md4.buf); md->md4.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->md4.curlen < 56) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } /* store length */ #ifdef HAVE_NATIVE_INT64 STORE64L(md->md4.length, md->md4.buf+56); #else STORE32L(md->md4.lengthLo, md->md4.buf+56); STORE32L(md->md4.lengthHi, md->md4.buf+60); #endif /* HAVE_NATIVE_INT64 */ md4_compress(md, md->md4.buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md->md4.state[i], out+(4*i)); } memset(md, 0x0, sizeof(psDigestContext_t)); return PS_SUCCESS; }
/* Test store/load macros with offsets */ int store_test(void) { unsigned char buf[256]; int y; ulong32 L, L1; ulong64 LL, LL1; #ifdef LTC_FAST int x, z; #endif for (y = 0; y < 4; y++) { L = 0x12345678UL; L1 = 0; STORE32L(L, buf + y); LOAD32L(L1, buf + y); if (L1 != L) { fprintf(stderr, "\n32L failed at offset %d\n", y); return 1; } STORE32H(L, buf + y); LOAD32H(L1, buf + y); if (L1 != L) { fprintf(stderr, "\n32H failed at offset %d\n", y); return 1; } } for (y = 0; y < 8; y++) { LL = CONST64 (0x01020304050607); LL1 = 0; STORE64L(LL, buf + y); LOAD64L(LL1, buf + y); if (LL1 != LL) { fprintf(stderr, "\n64L failed at offset %d\n", y); return 1; } STORE64H(LL, buf + y); LOAD64H(LL1, buf + y); if (LL1 != LL) { fprintf(stderr, "\n64H failed at offset %d\n", y); return 1; } } /* test LTC_FAST */ #ifdef LTC_FAST y = 16; for (z = 0; z < y; z++) { /* fill y bytes with random */ yarrow_read(buf+z, y, &yarrow_prng); yarrow_read(buf+z+y, y, &yarrow_prng); /* now XOR it byte for byte */ for (x = 0; x < y; x++) { buf[2*y+z+x] = buf[z+x] ^ buf[z+y+x]; } /* now XOR it word for word */ for (x = 0; x < y; x += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE*)(&buf[3*y+z+x])) = *((LTC_FAST_TYPE*)(&buf[z+x])) ^ *((LTC_FAST_TYPE*)(&buf[z+y+x])); } if (memcmp(&buf[2*y+z], &buf[3*y+z], y)) { fprintf(stderr, "\nLTC_FAST failed at offset %d\n", z); return 1; } } #endif return 0; }
/** Sign a message digest using a DH private key @param in The data to sign @param inlen The length of the input (octets) @param out [out] The destination of the signature @param outlen [in/out] The max size and resulting size of the output @param prng An active PRNG state @param wprng The index of the PRNG desired @param key A private DH key @return CRYPT_OK if successful */ int dh_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, dh_key *key) { mp_int a, b, k, m, g, p, p1, tmp; unsigned char *buf; unsigned long x, y; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* check parameters */ if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } /* is the IDX valid ? */ if (is_valid_idx(key->idx) != 1) { return CRYPT_PK_INVALID_TYPE; } /* allocate ram for buf */ buf = XMALLOC(520); /* make up a random value k, * since the order of the group is prime * we need not check if gcd(k, r) is 1 */ if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) != (unsigned long)(sets[key->idx].size)) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } /* init bignums */ if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) { err = mpi_to_ltc_error(err); goto LBL_ERR; } /* load k and m */ if ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; } if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY) { goto error; } /* load g, p and p1 */ if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; } if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; } if ((err = mp_sub_d(&p, 1, &p1)) != MP_OKAY) { goto error; } if ((err = mp_div_2(&p1, &p1)) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */ /* now get a = g^k mod p */ if ((err = mp_exptmod(&g, &k, &p, &a)) != MP_OKAY) { goto error; } /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */ if ((err = mp_invmod(&k, &p1, &k)) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */ if ((err = mp_mulmod(&a, &key->x, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = xa */ if ((err = mp_submod(&m, &tmp, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = M - xa */ if ((err = mp_mulmod(&k, &tmp, &p1, &b)) != MP_OKAY) { goto error; } /* b = (M - xa)/k */ /* check for overflow */ if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* store header */ y = PACKET_SIZE; /* now store them both (a,b) */ x = (unsigned long)mp_unsigned_bin_size(&a); STORE32L(x, out+y); y += 4; if ((err = mp_to_unsigned_bin(&a, out+y)) != MP_OKAY) { goto error; } y += x; x = (unsigned long)mp_unsigned_bin_size(&b); STORE32L(x, out+y); y += 4; if ((err = mp_to_unsigned_bin(&b, out+y)) != MP_OKAY) { goto error; } y += x; /* check if size too big */ if (*outlen < y) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* store header */ packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED); *outlen = y; err = CRYPT_OK; goto LBL_ERR; error: err = mpi_to_ltc_error(err); LBL_ERR: mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL); XFREE(buf); return err; }
/** Encrypt a short symmetric key with a public DH key @param in The symmetric key to encrypt @param inlen The length of the key (octets) @param out [out] The ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param prng An active PRNG state @param wprng The index of the PRNG desired @param hash The index of the hash desired (must produce a digest of size >= the size of the plaintext) @param key The public key you wish to encrypt with. @return CRYPT_OK if successful */ int dh_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, int hash, dh_key *key) { unsigned char *pub_expt, *dh_shared, *skey; dh_key pubkey; unsigned long x, y, z, hashsize, pubkeysize; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* check that wprng/hash are not invalid */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (inlen > hash_descriptor[hash].hashsize) { return CRYPT_INVALID_HASH; } /* allocate memory */ pub_expt = XMALLOC(DH_BUF_SIZE); dh_shared = XMALLOC(DH_BUF_SIZE); skey = XMALLOC(MAXBLOCKSIZE); if (pub_expt == NULL || dh_shared == NULL || skey == NULL) { if (pub_expt != NULL) { XFREE(pub_expt); } if (dh_shared != NULL) { XFREE(dh_shared); } if (skey != NULL) { XFREE(skey); } return CRYPT_MEM; } /* make a random key and export the public copy */ if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) { goto LBL_ERR; } pubkeysize = DH_BUF_SIZE; if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { dh_free(&pubkey); goto LBL_ERR; } /* now check if the out buffer is big enough */ if (*outlen < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + inlen)) { dh_free(&pubkey); err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* make random key */ hashsize = hash_descriptor[hash].hashsize; x = DH_BUF_SIZE; if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) { dh_free(&pubkey); goto LBL_ERR; } dh_free(&pubkey); z = MAXBLOCKSIZE; if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) { goto LBL_ERR; } /* store header */ packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY); /* output header */ y = PACKET_SIZE; /* size of hash name and the name itself */ out[y++] = hash_descriptor[hash].ID; /* length of DH pubkey and the key itself */ STORE32L(pubkeysize, out+y); y += 4; for (x = 0; x < pubkeysize; x++, y++) { out[y] = pub_expt[x]; } /* Store the encrypted key */ STORE32L(inlen, out+y); y += 4; for (x = 0; x < inlen; x++, y++) { out[y] = skey[x] ^ in[x]; } *outlen = y; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK /* clean up */ zeromem(pub_expt, DH_BUF_SIZE); zeromem(dh_shared, DH_BUF_SIZE); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(skey); XFREE(dh_shared); XFREE(pub_expt); return err; }