int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg, const struct iovec *iov, size_t niov, uint8_t **result, size_t *resultlen, Error **errp) { int i, ret; gnutls_hash_hd_t dig; if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map)) { error_setg(errp, "Unknown hash algorithm %d", alg); return -1; } ret = gnutls_hash_init(&dig, qcrypto_hash_alg_map[alg]); if (ret < 0) { error_setg(errp, "Unable to initialize hash algorithm: %s", gnutls_strerror(ret)); return -1; } for (i = 0; i < niov; i++) { ret = gnutls_hash(dig, iov[i].iov_base, iov[i].iov_len); if (ret < 0) { error_setg(errp, "Unable process hash data: %s", gnutls_strerror(ret)); goto error; } } ret = gnutls_hash_get_len(qcrypto_hash_alg_map[alg]); if (ret <= 0) { error_setg(errp, "Unable to get hash length: %s", gnutls_strerror(ret)); goto error; } if (*resultlen == 0) { *resultlen = ret; *result = g_new0(uint8_t, *resultlen); } else if (*resultlen != ret) { error_setg(errp, "Result buffer size %zu is smaller than hash %d", *resultlen, ret); goto error; } gnutls_hash_deinit(dig, *result); return 0; error: gnutls_hash_deinit(dig, NULL); return -1; }
void crypto_md5_final(CryptoMd5 md5, uint8 * out_data) { /* Assuming out_data has room for gnutls_hash_get_len(GNUTLS_DIG_MD5) */ gnutls_hash_deinit(md5->dig, out_data); xfree(md5); }
void Digest::recycle(bool bin) { unsigned size = bufsize; if(!context || hashid == 0) return; if(!bufsize) { gnutls_hash_deinit((MD_CTX)context, buffer); context = NULL; gnutls_hash_init((MD_CTX *)&context, (MD_ID)hashid); } else Digest::reset(); size = gnutls_hash_get_len((MD_ID)hashid); if(!size || !context || !hashid) return; if(bin) gnutls_hash((MD_CTX)context, buffer, size); else { unsigned count = 0; while(count < size) { snprintf(textbuf + (count * 2), 3, "%2.2x", buffer[count]); ++count; } gnutls_hash((MD_CTX)context, textbuf, size * 2); } bufsize = 0; }
// Nothing to deallocate, constructor may throw freely Hash(const std::string& hashname) { // As older versions of gnutls can't do this, let's disable it where needed. #ifdef GNUTLS_HAS_MAC_GET_ID // As gnutls_digest_algorithm_t and gnutls_mac_algorithm_t are mapped 1:1, we can do this // There is no gnutls_dig_get_id() at the moment, but it may come later hash = (gnutls_digest_algorithm_t)gnutls_mac_get_id(hashname.c_str()); if (hash == GNUTLS_DIG_UNKNOWN) throw Exception("Unknown hash type " + hashname); // Check if the user is giving us something that is a valid MAC but not digest gnutls_hash_hd_t is_digest; if (gnutls_hash_init(&is_digest, hash) < 0) throw Exception("Unknown hash type " + hashname); gnutls_hash_deinit(is_digest, NULL); #else if (hashname == "md5") hash = GNUTLS_DIG_MD5; else if (hashname == "sha1") hash = GNUTLS_DIG_SHA1; #ifdef INSPIRCD_GNUTLS_ENABLE_SHA256_FINGERPRINT else if (hashname == "sha256") hash = GNUTLS_DIG_SHA256; #endif else throw Exception("Unknown hash type " + hashname); #endif }
void Cipher::Key::assign(const char *text, size_t size, const unsigned char *salt, unsigned count) { if(!hashid || !algoid) { keysize = 0; return; } size_t kpos = 0, ivpos = 0; size_t mdlen = gnutls_hash_get_len((MD_ID)hashid); size_t tlen = strlen(text); if(!hashid || !mdlen) { clear(); return; } char previous[MAX_DIGEST_HASHSIZE / 8]; unsigned char temp[MAX_DIGEST_HASHSIZE / 8]; MD_CTX mdc; unsigned prior = 0; unsigned loop; if(!salt) salt = _salt; if(!count) count = _rounds; do { gnutls_hash_init(&mdc, (MD_ID)hashid); if(prior++) gnutls_hash(mdc, previous, mdlen); gnutls_hash(mdc, text, tlen); if(salt) gnutls_hash(mdc, salt, 8); gnutls_hash_deinit(mdc, previous); for(loop = 1; loop < count; ++loop) { memcpy(temp, previous, mdlen); gnutls_hash_fast((MD_ID)hashid, temp, mdlen, previous); } size_t pos = 0; while(kpos < keysize && pos < mdlen) keybuf[kpos++] = previous[pos++]; while(ivpos < blksize && pos < mdlen) ivbuf[ivpos++] = previous[pos++]; } while(kpos < keysize || ivpos < blksize); }
void Digest::release(void) { if(context) { gnutls_hash_deinit((MD_CTX)context, buffer); context = NULL; } bufsize = 0; textbuf[0] = 0; hashid = 0; }
void Digest::reset(void) { unsigned char temp[MAX_DIGEST_HASHSIZE / 8]; if(context) { gnutls_hash_deinit((MD_CTX)context, temp); context = NULL; } if(hashid == 0) return; gnutls_hash_init((MD_CTX *)&context, (MD_ID)hashid); bufsize = 0; }
const unsigned char *Digest::get(void) { unsigned count = 0; unsigned size = 0; if(bufsize) return buffer; if(!context || hashid == 0) return NULL; gnutls_hash_deinit((MD_CTX)context, buffer); size = gnutls_hash_get_len((MD_ID)hashid); context = NULL; bufsize = size; while(count < bufsize) { snprintf(textbuf + (count * 2), 3, "%2.2x", buffer[count]); ++count; } return buffer; }
static void DoExtFileHashing_FD(tBuffer *bIn, tBuffer *bOut, u_int32_t id, int fd) { gnutls_digest_algorithm_t gnuTlsAlgo = GNUTLS_DIG_UNKNOWN; u_int64_t offset, length; u_int32_t blockSize; char *algo; algo = BufferGetString(bIn); offset = BufferGetInt64(bIn); length = BufferGetInt64(bIn); blockSize = BufferGetInt32(bIn); if (lseek(fd, offset, SEEK_SET) == -1) { SendStatus(bOut, id, errnoToPortable(errno)); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error lseek1")); goto endOfFileHashing; } if (length == 0)//read the file to the end { u_int64_t endOfFile; if ((endOfFile = lseek(fd, 0, SEEK_END)) == -1) { SendStatus(bOut, id, errnoToPortable(errno)); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error lseek2")); goto endOfFileHashing; } length = endOfFile - offset; if (lseek(fd, offset, SEEK_SET) == -1) { SendStatus(bOut, id, errnoToPortable(errno)); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error lseek3")); goto endOfFileHashing; } } if (blockSize == 0)//read length in one time blockSize = length; DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Algo:%s Fd:%i Offset:%llu Length:%llu BlockSize:%i", algo, fd, offset, length, blockSize)); if (strcasecmp("md2", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_MD2; else if (strcasecmp("md5", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_MD5; else if (strcasecmp("sha1", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA1; else if (strcasecmp("sha224", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA224; else if (strcasecmp("sha256", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA256; else if (strcasecmp("sha384", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA384; else if (strcasecmp("sha512", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA512; if (gnuTlsAlgo != GNUTLS_DIG_UNKNOWN) { gnutls_hash_hd_t dig; tBuffer *b; size_t keySize = gnutls_hash_get_len(gnuTlsAlgo); char *gnuKey; char data[SSH2_READ_HASH]; int inError = 0; int gnulTlsError; b = BufferNew(); BufferPutInt8FAST(b, SSH2_FXP_EXTENDED_REPLY); BufferPutInt32(b, id); BufferPutString(b, algo); gnuKey = calloc(1, keySize); if (gnuKey == NULL) goto endOfFileHashing; if ((gnulTlsError = gnutls_hash_init(&dig, gnuTlsAlgo)) == 0) { while (length > 0) { u_int32_t r, off, len; length = (length > (u_int64_t) blockSize) ? length - (u_int64_t) blockSize : 0; off = blockSize; len = sizeof(data); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Read:%i Rest:%llu", len, length)); while ((r = read(fd, data, len)) > 0) { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Compute block (%u/%u %u)", len, r, off)); if ((gnulTlsError = gnutls_hash(dig, data, r)) != 0) { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error gnutls_hmac [error: %i]", gnulTlsError)); inError = 1; break; } off -= r; if (off < sizeof(data)) len = off; if (off == 0) break; } } } else { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error gnutls_hash_init [keySize: %li] [error: %i]", keySize, gnulTlsError)); inError = 1; } if (inError == 0) { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Compute key... [keySize: %li][keyPointer: %p]", keySize, gnuKey)); gnutls_hash_deinit(dig, gnuKey); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Hash: %X%X%X ...", gnuKey[0], gnuKey[1], gnuKey[2])); BufferPutRawData(b, gnuKey, keySize); BufferPutPacket(bOut, b); } else SendStatus(bOut, id, SSH2_FX_FAILURE); BufferDelete(b); free(gnuKey); } else { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]No algorithm: %s", algo)); SendStatus(bOut, id, SSH2_FX_OP_UNSUPPORTED); } endOfFileHashing: DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]End")); free(algo); }
void crypto_sha1_final(CryptoSha1 sha1, uint8 * out_data) { gnutls_hash_deinit(sha1->dig, out_data); xfree(sha1); }
CryptoDigest::~CryptoDigest() { gnutls_hash_deinit(m_context->hash, 0); }
gboolean crypto_md5_hash (const char *salt, const gsize salt_len, const char *password, gsize password_len, char *buffer, gsize buflen, GError **error) { gnutls_hash_hd_t ctx; int err; int nkey = buflen; const gsize digest_len = 16; int count = 0; char digest[MD5_HASH_LEN]; char *p = buffer; if (salt) g_return_val_if_fail (salt_len >= SALT_LEN, FALSE); g_return_val_if_fail (password != NULL, FALSE); g_return_val_if_fail (password_len > 0, FALSE); g_return_val_if_fail (buffer != NULL, FALSE); g_return_val_if_fail (buflen > 0, FALSE); if (gnutls_hash_get_len (GNUTLS_DIG_MD5) > MD5_HASH_LEN) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_MD5_INIT_FAILED, _("Hash length too long (%d > %d)."), gnutls_hash_get_len (GNUTLS_DIG_MD5), MD5_HASH_LEN); return FALSE; } while (nkey > 0) { int i = 0; err = gnutls_hash_init (&ctx, GNUTLS_DIG_MD5); if (err < 0) goto error; if (count++) gnutls_hash (ctx, digest, digest_len); gnutls_hash (ctx, password, password_len); if (salt) gnutls_hash (ctx, salt, SALT_LEN); /* Only use 8 bytes of salt */ gnutls_hash_deinit (ctx, digest); while (nkey && (i < digest_len)) { *(p++) = digest[i++]; nkey--; } } memset (digest, 0, sizeof (digest)); return TRUE; error: memset (digest, 0, sizeof (digest)); g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_MD5_INIT_FAILED, _("Failed to initialize the MD5 engine: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); return FALSE; }