/* Callback to extract a big int (stream of bytes) from the DER stream */ int32 getAsnBig(psPool_t *pool, unsigned char **pp, uint32 len, pstm_int *big) { unsigned char *p = *pp; uint32 vlen; if (len < 1 || *(p++) != ASN_INTEGER || getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) { psTraceCrypto("ASN getBig failed\n"); return PS_PARSE_FAIL; } /* Make a smart size since we know the length */ if (pstm_init_for_read_unsigned_bin(pool, big, vlen) != PSTM_OKAY) { return PS_MEM_FAIL; } if (pstm_read_unsigned_bin(big, p, vlen) != 0) { pstm_clear(big); psTraceCrypto("ASN getBig failed\n"); return PS_PARSE_FAIL; } p += vlen; *pp = p; return PS_SUCCESS; }
/* Get the BIT STRING key and plug into RSA structure. */ int32 getAsnRsaPubKey(psPool_t *pool, unsigned char **pp, uint32 len, psRsaKey_t *pubKey) { unsigned char *p = *pp; uint32 pubKeyLen, seqLen; int32 ignore_bits; memset(pubKey, 0x0, sizeof(psRsaKey_t)); if (len < 1 || (*(p++) != ASN_BIT_STRING) || getAsnLength(&p, len - 1, &pubKeyLen) < 0 || (len - 1) < pubKeyLen) { psTraceCrypto("Initial parse error in getAsnRsaPubKey\n"); return PS_PARSE_FAIL; } ignore_bits = *p++; /* We assume this is always zero */ psAssert(ignore_bits == 0); if (getAsnSequence(&p, pubKeyLen, &seqLen) < 0 || getAsnBig(pool, &p, seqLen, &pubKey->N) < 0 || getAsnBig(pool, &p, seqLen, &pubKey->e) < 0) { psTraceCrypto("Secondary parse error in getAsnRsaPubKey\n"); return PS_PARSE_FAIL; } pubKey->size = pstm_unsigned_bin_size(&pubKey->N); *pp = p; return PS_SUCCESS; }
/* Decrypt from libsodium will perform itself the tag comparaison. So ct is holding: cipher text || tag . The provided length (ctLen) must reflect this */ int32_t psAesDecryptGCM(psAesGcm_t *ctx, const unsigned char *ct, uint32_t ctLen, unsigned char *pt, uint32_t ptLen) { unsigned long long decrypted_len; if ((ctLen - ptLen) != crypto_aead_aes256gcm_ABYTES) { psTraceCrypto("Cipher text must include the tag\n"); return PS_ARG_FAIL; } if (crypto_aead_aes256gcm_decrypt_afternm(pt, &decrypted_len, NULL, ct, (unsigned long long) ctLen, (const unsigned char *) ctx->Aad, (unsigned long long) ctx->AadLen, (const unsigned char *) ctx->IV, (crypto_aead_aes256gcm_state *) &(ctx->libSodiumCtx)) != 0) { psTraceCrypto("GCM didn't authenticate\n"); return PS_AUTH_FAIL; } if (decrypted_len != ptLen) { psTraceCrypto("Problem during decryption\n"); return PS_AUTH_FAIL; } return PS_SUCCESS; }
/* On success, p will be updated to point to first character of value and valLen will contain number of bytes in value. Indefinite length formats return ASN_UNKNOWN_LEN and *valLen will simply be updated with the overall remaining length */ int32 getAsnLength(unsigned char **p, uint32 size, uint32 *valLen) { unsigned char *c, *end; uint32 len, olen; c = *p; end = c + size; *valLen = 0; if (end - c < 1) { psTraceCrypto("getAsnLength called on empty buffer\n"); return PS_LIMIT_FAIL; } /* If the length byte has high bit only set, it's an indefinite length */ if (*c == 0x80) { psTraceCrypto("Danger: ASN indefinite length\n"); c++; *p = c; *valLen = size - 1; return ASN_UNKNOWN_LEN; } /* If the high bit is set, the lower 7 bits represent the number of bytes that follow and represent length If the high bit is not set, the lower 7 represent the actual length */ len = *c & 0x7F; if (*(c++) & 0x80) { /* Make sure there aren't more than 4 bytes of length specifier, and that we have that many bytes left in the buffer */ if (len > sizeof(int32) || len == 0x7f || (uint32)(end - c) < len) { psTraceCrypto("Malformed stream in getAsnLength\n"); return PS_LIMIT_FAIL; } olen = 0; while (len-- > 0) { olen = (olen << 8) | *c; c++; } if (olen > INT_MAX) { psTraceCrypto("Malformed stream in getAsnLength\n"); return PS_LIMIT_FAIL; } len = olen; } *p = c; *valLen = len; return PS_SUCCESS; }
psResSize_t psChacha20Poly1305IetfDecryptDetached( psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], const unsigned char *Ciphertext_p, psSizeL_t CiphertextNBytes, const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], const unsigned char *Aad_p, psSizeL_t AadNBytes, const unsigned char Mac_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_ABYTES)], unsigned char *Plaintext_p) { psSizeL_t plaintextNBytes = CiphertextNBytes; /* Plaintext length is the same than ciphertext length. */ /* Check input is not too large for this API. */ if (plaintextNBytes > (psSizeL_t)(psResSize_t)PS_RES_SIZE_OK_MAX) { return PS_ARG_FAIL; } if (psCrypto_aead_chacha20poly1305_ietf_decrypt_detached( Plaintext_p, NULL, Ciphertext_p, (unsigned long long)CiphertextNBytes, (const unsigned char *)Mac_p, (const unsigned char *)Aad_p, (unsigned long long)AadNBytes, (const unsigned char *)Iv_p, (const unsigned char *)Context_p->key) != 0) { psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); return PS_AUTH_FAIL; } return (psResSize_t)plaintextNBytes; }
int32 psHmacSha2Final(psHmacContext_t *ctx, unsigned char *hash, uint32 hashSize) { psAssert(ctx != NULL); if (hash == NULL) { psTraceCrypto("NULL hash storage passed to psHmacSha256Final\n"); return PS_ARG_FAIL; } if (hashSize == SHA384_HASH_SIZE) { #ifdef USE_SHA384 psSha384Final(&ctx->u.sha512, hash); psSha384Init(&ctx->u.sha512); psSha384Update(&ctx->u.sha512, ctx->pad, 128); psSha384Update(&ctx->u.sha512, hash, SHA384_HASH_SIZE); psSha384Final(&ctx->u.sha512, hash); #else return PS_UNSUPPORTED_FAIL; #endif } else { psSha256Final(&ctx->u.sha256, hash); psSha256Init(&ctx->u.sha256); psSha256Update(&ctx->u.sha256, ctx->pad, 64); psSha256Update(&ctx->u.sha256, hash, SHA256_HASH_SIZE); psSha256Final(&ctx->u.sha256, hash); } memset(ctx->pad, 0x0, sizeof(ctx->pad)); return hashSize; }
int32 psMd2Update(psDigestContext_t *md, const unsigned char *buf, uint32 len) { uint32 n; psAssert(md != NULL); psAssert(buf != NULL); if (md->md2.curlen > sizeof(md->md2.buf)) { psTraceCrypto("psMd2Update error\n"); return PS_LIMIT_FAIL; } while (len > 0) { n = min(len, (16 - md->md2.curlen)); memcpy(md->md2.buf + md->md2.curlen, buf, (size_t)n); md->md2.curlen += n; buf += n; len -= n; /* is 16 bytes full? */ if (md->md2.curlen == 16) { md2_compress(md); md2_update_chksum(md); md->md2.curlen = 0; } } return PS_SUCCESS; }
int32 psArc4(psCipherContext_t *ctx, unsigned char *in, unsigned char *out, uint32 len) { unsigned char x, y, *state, xorIndex, tmp; uint32 counter; ctx->arc4.byteCount += len; if (ctx->arc4.byteCount > ARC4_MAX_BYTES) { psTraceCrypto("ARC4 byteCount overrun\n"); return PS_LIMIT_FAIL; } x = ctx->arc4.x; y = ctx->arc4.y; state = &ctx->arc4.state[0]; for (counter = 0; counter < len; counter++) { x = (x + 1) & 0xff; y = (state[x] + y) & 0xff; tmp = state[x]; state[x] = state[y]; state[y] = tmp; xorIndex = (state[x] + state[y]) & 0xff; tmp = in[counter]; tmp ^= state[xorIndex]; out[counter] = tmp; } ctx->arc4.x = x; ctx->arc4.y = y; return len; }
int32_t psMd2Update(psMd2_t *md, const unsigned char *buf, uint32_t len) { uint32_t n; # ifdef CRYPTO_ASSERT psAssert(md != NULL); psAssert(buf != NULL); if (md->curlen > sizeof(md->buf)) { psTraceCrypto("psMd2Update error\n"); return PS_LIMIT_FAIL; } # endif while (len > 0) { n = min(len, (16 - md->curlen)); memcpy(md->buf + md->curlen, buf, (size_t) n); md->curlen += n; buf += n; len -= n; /* is 16 bytes full? */ if (md->curlen == 16) { md2_compress(md); md2_update_chksum(md); md->curlen = 0; } } return PS_SUCCESS; }
int32 psMd2Final(psDigestContext_t * md, unsigned char *hash) { uint32 i, k; psAssert(md != NULL); psAssert(hash != NULL); if (md->md2.curlen >= sizeof(md->md2.buf)) { psTraceCrypto("psMd2Final error\n"); return PS_LIMIT_FAIL; } /* pad the message */ k = 16 - md->md2.curlen; for (i = md->md2.curlen; i < 16; i++) { md->md2.buf[i] = (unsigned char)k; } /* hash and update */ md2_compress(md); md2_update_chksum(md); /* hash checksum */ memcpy(md->md2.buf, md->md2.chksum, 16); md2_compress(md); /* output is lower 16 bytes of X */ memcpy(hash, md->md2.X, 16); memset(md, 0x0, sizeof(psDigestContext_t)); return PS_SUCCESS; }
/* Decrypt data using chach20-poly1305 authenticated encryption function. */ psResSize_t psChacha20Poly1305IetfDecrypt( psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], const unsigned char Ciphertext_p[PS_EXACTLY_EXPR(CiphertextNBytes)], psSizeL_t CiphertextNBytes, const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], const unsigned char *Aad_p, psSizeL_t AadNBytes, unsigned char *Plaintext_p) { #ifdef USE_PS_CRYPTO_AEAD_CHACHA20POLY1305_IETF_DECRYPT /* Old path, which can be enabled by setting USE_PS_CRYPTO_AEAD_CHACHA20POLY1305_IETF_DECRYPT. */ psSizeL_t plaintextNBytes = CiphertextNBytes - PS_CHACHA20POLY1305_IETF_ABYTES; if (CiphertextNBytes < PS_CHACHA20POLY1305_IETF_ABYTES) { return PS_ARG_FAIL; } /* Check input is not too large for this API. */ if (plaintextNBytes > (psSizeL_t)(psResSize_t)PS_RES_SIZE_OK_MAX) { return PS_ARG_FAIL; } if (psCrypto_aead_chacha20poly1305_ietf_decrypt( Plaintext_p, NULL, NULL, Ciphertext_p, (unsigned long long)CiphertextNBytes, (const unsigned char *)Aad_p, (unsigned long long)AadNBytes, (const unsigned char *)Iv_p, (const unsigned char *)Context_p->key) != 0) { psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); return PS_AUTH_FAIL; } return (psResSize_t)plaintextNBytes; #else psSizeL_t plaintextNBytes; /* Ensure input is not too short. */ if (CiphertextNBytes < PS_CHACHA20POLY1305_IETF_ABYTES) { return PS_ARG_FAIL; } plaintextNBytes = CiphertextNBytes - PS_CHACHA20POLY1305_IETF_ABYTES; return psChacha20Poly1305IetfDecryptDetached( Context_p, Ciphertext_p, plaintextNBytes, Iv_p, Aad_p, AadNBytes, Ciphertext_p + plaintextNBytes, Plaintext_p); #endif }
/* Get an integer */ int32 getAsnInteger(unsigned char **pp, uint32 len, int32 *val) { unsigned char *p = *pp, *end; uint32 ui, vlen; int32 slen; end = p + len; if (len < 1 || *(p++) != ASN_INTEGER || getAsnLength(&p, len - 1, &vlen) < 0) { psTraceCrypto("ASN getInteger failed from the start\n"); return PS_PARSE_FAIL; } /* This check prevents us from having a big positive integer where the high bit is set because it will be encoded as 5 bytes (with leading blank byte). If that is required, a getUnsigned routine should be used */ if (vlen > sizeof(int32) || (uint32)(end - p) < vlen) { psTraceCrypto("ASN getInteger had limit failure\n"); return PS_LIMIT_FAIL; } ui = 0; /* If high bit is set, it's a negative integer, so perform the two's compliment Otherwise do a standard big endian read (most likely case for RSA) */ if (*p & 0x80) { while (vlen-- > 0) { ui = (ui << 8) | (*p ^ 0xFF); p++; } slen = (int32)ui; slen++; slen = -slen; *val = slen; } else { while (vlen-- > 0) { ui = (ui << 8) | *p; p++; } *val = (int32)ui; } *pp = p; return PS_SUCCESS; }
int32_t psAesInitGCM(psAesGcm_t *ctx, const unsigned char key[AES_MAXKEYLEN], uint8_t keylen) { /* Check that structure is 16bytes aligned: */ if (((uintptr_t) (const void *) (&(ctx->libSodiumCtx))) % 16 != 0) { psTraceCrypto("\nFAIL: libsodium structure not 16bytes aligned"); printf("FAIL: libsodium structure not 16bytes aligned %p", &(ctx->libSodiumCtx)); psAssert(0); return PS_FAIL; } /* libsodium only supports aes256, not aes128 */ if (keylen != crypto_aead_aes256gcm_KEYBYTES) { psTraceCrypto("FAIL: libsodium-aes doesn't support this key length"); psAssert(keylen == crypto_aead_aes256gcm_KEYBYTES); return PS_FAIL; } if (sodium_init() != 0) { /* libsodium is already initialized, no problem */ } if (crypto_aead_aes256gcm_is_available() == 0) { psTraceCrypto("FAIL: libsodium-aes not supported"); psAssert(0); return PS_FAIL; } memset(ctx, 0x00, sizeof(psAesGcm_t)); if (crypto_aead_aes256gcm_beforenm(&(ctx->libSodiumCtx), key) != 0) { psTraceCrypto("FAIL: libsodium-aes init"); psAssert(0); return PS_FAIL; } return PS_SUCCESS; }
/* Extract a set length from the DER stream */ int32 getAsnSet(unsigned char **pp, uint32 len, uint32 *setlen) { unsigned char *p = *pp; if (len < 1 || *(p++) != (ASN_SET | ASN_CONSTRUCTED) || getAsnLength(&p, len - 1, setlen) < 0 || len < *setlen) { psTraceCrypto("ASN getSet failed\n"); return PS_PARSE_FAIL; } *pp = p; return PS_SUCCESS; }
/* #define DISABLE_STRICT_ASN_LENGTH_CHECK */ int32 getAsnSequence(unsigned char **pp, uint32 len, uint32 *seqlen) { unsigned char *p = *pp; if (len < 1 || *(p++) != (ASN_SEQUENCE | ASN_CONSTRUCTED) || getAsnLength(&p, len - 1, seqlen) < 0) { psTraceCrypto("ASN getSequence failed\n"); return PS_PARSE_FAIL; } #ifndef DISABLE_STRICT_ASN_LENGTH_CHECK if (len < *seqlen) { /* It isn't cool but some encodings have an outer length layer that is smaller than the inner. Normally you'll want this check but if you're hitting this case, you could try skipping it to see if there is an error in the encoding */ psTraceCrypto("ASN_SEQUENCE parse found length greater than total\n"); psTraceCrypto("Could try enabling DISABLE_STRICT_ASN_LENGTH_CHECK\n"); return PS_LIMIT_FAIL; } #endif *pp = p; return PS_SUCCESS; }
/* Implementation specific OID parser for suppported RSA algorithms */ int32 getAsnAlgorithmIdentifier(unsigned char **pp, uint32 len, int32 *oi, int32 isPubKey, int32 *paramLen) { unsigned char *p = *pp, *end; int32 plen; uint32 llen, arcLen; end = p + len; if (len < 1 || getAsnSequence(&p, len, &llen) < 0) { psTraceCrypto("getAsnAlgorithmIdentifier failed on inital parse\n"); return PS_PARSE_FAIL; } if (end - p < 1) { psTraceCrypto("Malformed algorithmId\n"); return PS_LIMIT_FAIL; } plen = end - p; if (*(p++) != ASN_OID || getAsnLength(&p, (uint32)(end - p), &arcLen) < 0 || llen < arcLen) { psTraceCrypto("Malformed algorithmId 2\n"); return PS_PARSE_FAIL; } if (end - p < 2) { psTraceCrypto("Malformed algorithmId 3\n"); return PS_LIMIT_FAIL; } if (isPubKey && (*p != 0x2a) && (*(p + 1) != 0x86)) { /* Expecting DSA here if not RSA, but OID doesn't always match */ psTraceCrypto("Unsupported algorithm identifier\n"); return PS_UNSUPPORTED_FAIL; } *oi = 0; while (arcLen-- > 0) { *oi += (int32)*p; p++; } /* Each of these cases might have a trailing NULL parameter. Skip it */ plen -= (end - p); *paramLen = llen - plen; if (*p != ASN_NULL) { *pp = p; return PS_SUCCESS; } if (end - p < 2) { psTraceCrypto("Malformed algorithmId 4\n"); return PS_LIMIT_FAIL; } *paramLen -= 2; *pp = p + 2; return PS_SUCCESS; }
int32 psHmacSha1Final(psHmacContext_t *ctx, unsigned char *hash) { psAssert(ctx != NULL); if (hash == NULL) { psTraceCrypto("NULL hash storage passed to psHmacSha1Final\n"); return PS_ARG_FAIL; } psSha1Final(&ctx->u.sha1, hash); psSha1Init(&ctx->u.sha1); psSha1Update(&ctx->u.sha1, ctx->pad, 64); psSha1Update(&ctx->u.sha1, hash, SHA1_HASH_SIZE); psSha1Final(&ctx->u.sha1, hash); memset(ctx->pad, 0x0, 64); return SHA1_HASH_SIZE; }
int32 psHmacMd5Final(psHmacContext_t *ctx, unsigned char *hash) { psAssert(ctx != NULL); if (hash == NULL) { psTraceCrypto("NULL hash storage passed to psHmacMd5Final\n"); return PS_ARG_FAIL; } psMd5Final(&ctx->u.md5, hash); psMd5Init(&ctx->u.md5); psMd5Update(&ctx->u.md5, ctx->pad, 64); psMd5Update(&ctx->u.md5, hash, MD5_HASH_SIZE); psMd5Final(&ctx->u.md5, hash); memset(ctx->pad, 0x0, 64); return MD5_HASH_SIZE; }
/* Specifiy the IV and additional data to an AES GCM context that was created with psAesInitGCM */ void psAesReadyGCM(psAesGcm_t *ctx, const unsigned char IV[AES_IVLEN], const unsigned char *aad, psSize_t aadLen) { /* --- Set up context structure ---// */ /* Set up IV (nonce) */ memset(ctx->IV, 0, 16); memcpy(ctx->IV, IV, 12); if (aadLen > sizeof(ctx->Aad)) { psTraceCrypto("FAIL: size issue"); psAssert(0); } /* Set up additional data */ memcpy(ctx->Aad, aad, aadLen); ctx->AadLen = aadLen; }
void psHmacSha1Final(psHmacSha1_t *ctx, unsigned char hash[SHA1_HASHLEN]) { int32_t rc; #ifdef CRYPTO_ASSERT psAssert(ctx != NULL); if (hash == NULL) { psTraceCrypto("NULL hash storage passed to psHmacSha1Final\n"); return; } #endif psSha1Final(&ctx->sha1, hash); if ((rc = psSha1Init(&ctx->sha1)) < 0) { psAssert(rc >= 0); return; } psSha1Update(&ctx->sha1, ctx->pad, 64); psSha1Update(&ctx->sha1, hash, SHA1_HASHLEN); psSha1Final(&ctx->sha1, hash); memset(ctx->pad, 0x0, sizeof(ctx->pad)); }
/* Decrypt will invoke GetGMCTag so the comparison can be done. ctLen will include the appended tag length and ptLen is just the encrypted portion */ int32_t psAesDecryptGCM(psAesGcm_t *ctx, const unsigned char *ct, uint32_t ctLen, unsigned char *pt, uint32_t ptLen) { uint16_t tagLen; unsigned char tag[AES_BLOCKLEN]; if (ctLen > ptLen) { tagLen = ctLen - ptLen; } else { return PS_ARG_FAIL; } psAesEncryptGCMx(ctx, ct, pt, ptLen, 0); psAesGetGCMTag(ctx, tagLen, tag); if (memcmpct(tag, ct + ptLen, tagLen) != 0) { psTraceCrypto("GCM didn't authenticate\n"); return PS_AUTH_FAIL; } return PS_SUCCESS; }
void psHmacMd5Final(psHmacMd5_t *ctx, unsigned char hash[MD5_HASHLEN]) { int32_t rc; #ifdef CRYPTO_ASSERT psAssert(ctx != NULL); if (hash == NULL) { psTraceCrypto("NULL hash storage passed to psHmacMd5Final\n"); return; } #endif psMd5Final(&ctx->md5, hash); /* This Init should succeed, even if it allocates memory since an psMd5_t was just Finalized the line above */ if ((rc = psMd5Init(&ctx->md5)) < 0) { psAssert(rc >= 0); return; } psMd5Update(&ctx->md5, ctx->pad, 64); psMd5Update(&ctx->md5, hash, MD5_HASHLEN); psMd5Final(&ctx->md5, hash); memset(ctx->pad, 0x0, sizeof(ctx->pad)); }
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; }
void psSha256Final(psSha256_t *sha256, unsigned char hash[SHA256_HASHLEN]) { int32 i; #ifndef HAVE_NATIVE_INT64 uint32 n; #endif #ifdef CRYPTO_ASSERT psAssert(sha256 != NULL); psAssert(hash != NULL); if (sha256->curlen >= sizeof(sha256->buf)) { psTraceCrypto("psSha256Final error\n"); return; } #endif /* increase the length of the message */ #ifdef HAVE_NATIVE_INT64 sha256->length += sha256->curlen << 3; #else n = (sha256->lengthLo + (sha256->curlen << 3)) & 0xFFFFFFFFL; if (n < sha256->lengthLo) { sha256->lengthHi++; } sha256->lengthHi += (sha256->curlen >> 29); sha256->lengthLo = n; #endif /* HAVE_NATIVE_INT64 */ /* append the '1' bit */ sha256->buf[sha256->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 (sha256->curlen > 56) { while (sha256->curlen < 64) { sha256->buf[sha256->curlen++] = (unsigned char)0; } sha256_compress(sha256, sha256->buf); sha256->curlen = 0; } /* pad upto 56 bytes of zeroes */ while (sha256->curlen < 56) { sha256->buf[sha256->curlen++] = (unsigned char)0; } /* store length */ #ifdef HAVE_NATIVE_INT64 STORE64H(sha256->length, sha256->buf+56); #else STORE32H(sha256->lengthHi, sha256->buf+56); STORE32H(sha256->lengthLo, sha256->buf+60); #endif /* HAVE_NATIVE_INT64 */ sha256_compress(sha256, sha256->buf); /* copy output */ for (i = 0; i < 8; i++) { STORE32H(sha256->state[i], hash+(4*i)); } memset(sha256, 0x0, sizeof(psSha256_t)); }
int32 psSha1Final(psDigestContext_t * md, unsigned char *hash) { int32 i; #ifndef HAVE_NATIVE_INT64 uint32 n; #endif psAssert(md != NULL); if (md->sha1.curlen >= sizeof(md->sha1.buf) || hash == NULL) { psTraceCrypto("psSha1Final error\n"); return PS_ARG_FAIL; } /* increase the length of the message */ #ifdef HAVE_NATIVE_INT64 md->sha1.length += md->sha1.curlen << 3; #else n = (md->sha1.lengthLo + (md->sha1.curlen << 3)) & 0xFFFFFFFFL; if (n < md->sha1.lengthLo) { md->sha1.lengthHi++; } md->sha1.lengthHi += (md->sha1.curlen >> 29); md->sha1.lengthLo = n; #endif /* HAVE_NATIVE_INT64 */ /* append the '1' bit */ md->sha1.buf[md->sha1.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->sha1.curlen > 56) { while (md->sha1.curlen < 64) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } sha1_compress(md); md->sha1.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->sha1.curlen < 56) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } /* store length */ #ifdef HAVE_NATIVE_INT64 STORE64H(md->sha1.length, md->sha1.buf+56); #else STORE32H(md->sha1.lengthHi, md->sha1.buf+56); STORE32H(md->sha1.lengthLo, md->sha1.buf+60); #endif /* HAVE_NATIVE_INT64 */ sha1_compress(md); /* copy output */ for (i = 0; i < 5; i++) { STORE32H(md->sha1.state[i], hash+(4*i)); } memset(md, 0x0, sizeof(psDigestContext_t)); return SHA1_HASH_SIZE; }