/* [RFC 3414] - A.2. Password to Key Algorithm */ enum snmp_code snmp_passwd_to_keys(struct snmp_user *user, char *passwd) { int err, loop, i, pwdlen; uint32_t keylen, olen; const EVP_MD *dtype; EVP_MD_CTX ctx; uint8_t authbuf[SNMP_AUTH_BUF_SIZE]; if (passwd == NULL || user == NULL) return (SNMP_CODE_FAILED); err = snmp_digest_init(user, &ctx, &dtype, &keylen); if (err < 0) return (SNMP_CODE_BADDIGEST); else if (err == 0) return (SNMP_CODE_OK); memset(user->auth_key, 0, sizeof(user->auth_key)); pwdlen = strlen(passwd); for (loop = 0; loop < SNMP_AUTH_KEY_LOOPCNT; loop += i) { for (i = 0; i < SNMP_EXTENDED_KEY_SIZ; i++) authbuf[i] = passwd[(loop + i) % pwdlen]; if (EVP_DigestUpdate(&ctx, authbuf, SNMP_EXTENDED_KEY_SIZ) != 1) goto failed; } if (EVP_DigestFinal(&ctx, user->auth_key, &olen) != 1) goto failed; EVP_MD_CTX_cleanup(&ctx); return (SNMP_CODE_OK); failed: EVP_MD_CTX_cleanup(&ctx); return (SNMP_CODE_BADDIGEST); }
/* [RFC 3414] - 2.6. Key Localization Algorithm */ enum snmp_code snmp_get_local_keys(struct snmp_user *user, uint8_t *eid, uint32_t elen) { int err; uint32_t keylen, olen; const EVP_MD *dtype; EVP_MD_CTX ctx; uint8_t authbuf[SNMP_AUTH_BUF_SIZE]; if (user == NULL || eid == NULL || elen > SNMP_ENGINE_ID_SIZ) return (SNMP_CODE_FAILED); memset(user->priv_key, 0, sizeof(user->priv_key)); memset(authbuf, 0, sizeof(authbuf)); err = snmp_digest_init(user, &ctx, &dtype, &keylen); if (err < 0) return (SNMP_CODE_BADDIGEST); else if (err == 0) return (SNMP_CODE_OK); memcpy(authbuf, user->auth_key, keylen); memcpy(authbuf + keylen, eid, elen); memcpy(authbuf + keylen + elen, user->auth_key, keylen); if (EVP_DigestUpdate(&ctx, authbuf, 2 * keylen + elen) != 1 || EVP_DigestFinal(&ctx, user->auth_key, &olen) != 1) { EVP_MD_CTX_cleanup(&ctx); return (SNMP_CODE_BADDIGEST); } EVP_MD_CTX_cleanup(&ctx); if (user->priv_proto != SNMP_PRIV_NOPRIV) memcpy(user->priv_key, user->auth_key, sizeof(user->priv_key)); return (SNMP_CODE_OK); }
/* * hash a byte sequence with the specified algorithm */ apr_byte_t oidc_jose_hash_bytes(apr_pool_t *pool, const char *s_digest, const unsigned char *input, unsigned int input_len, unsigned char **output, unsigned int *output_len, oidc_jose_error_t *err) { unsigned char md_value[EVP_MAX_MD_SIZE]; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); EVP_MD_CTX_init(ctx); const EVP_MD *evp_digest = NULL; if ((evp_digest = EVP_get_digestbyname(s_digest)) == NULL) { oidc_jose_error(err, "no OpenSSL digest algorithm found for algorithm \"%s\"", s_digest); return FALSE; } if (!EVP_DigestInit_ex(ctx, evp_digest, NULL)) { oidc_jose_error_openssl(err, "EVP_DigestInit_ex"); return FALSE; } if (!EVP_DigestUpdate(ctx, input, input_len)) { oidc_jose_error_openssl(err, "EVP_DigestUpdate"); return FALSE; } if (!EVP_DigestFinal(ctx, md_value, output_len)) { oidc_jose_error_openssl(err, "EVP_DigestFinal"); return FALSE; } EVP_MD_CTX_free(ctx); *output = apr_pcalloc(pool, *output_len); memcpy(*output, md_value, *output_len); return TRUE; }
//Copied from aegis-crypto0 bin/accli.c int PackageUtils::computeDigest(int ih, unsigned char* digest, ssize_t maxdigestlen) { EVP_MD_CTX mdctx; unsigned int mdlen; unsigned char data[512]; int rc; ssize_t len; if (maxdigestlen < DIGESTLEN) return(-EINVAL); rc = EVP_DigestInit(&mdctx, DIGESTTYP()); if (EVPOK != rc) { qDebug()<<"EVP_DigestInit returns "<< rc; return 0; } while (0 < (len = read(ih, data, sizeof(data)))) { rc = EVP_DigestUpdate(&mdctx, data, len); if (EVPOK != rc) { qDebug()<<"EVP_DigestUpdate returns:"<<rc<<Q_FUNC_INFO; return 0; } if (len < sizeof(data)) break; } rc = EVP_DigestFinal(&mdctx, digest, &mdlen); if (rc != EVPOK) { qDebug()<<"EVP_DigestUpdate returns:"<<rc<<Q_FUNC_INFO; return(0); } EVP_MD_CTX_cleanup(&mdctx); return mdlen; }
/* * Not really public interface, * but common routine called from both client and server. */ int gfs_digest_calculate_local(int fd, char *buffer, size_t buffer_size, const EVP_MD *md_type, EVP_MD_CTX *md_ctx, size_t *md_lenp, unsigned char *md_value, file_offset_t *filesizep) { int size; file_offset_t off = 0; unsigned int len; if (lseek(fd, (off_t)0, 0) == -1) return (errno); EVP_DigestInit(md_ctx, md_type); while ((size = read(fd, buffer, buffer_size)) > 0) { EVP_DigestUpdate(md_ctx, buffer, size); off += size; } EVP_DigestFinal(md_ctx, md_value, &len); *md_lenp = len; *filesizep = off; return (size == -1 ? errno : 0); }
static PyObject * EVP_hexdigest(EVPobject *self, PyObject *unused) { unsigned char digest[EVP_MAX_MD_SIZE]; EVP_MD_CTX *temp_ctx; unsigned int digest_size; temp_ctx = EVP_MD_CTX_new(); if (temp_ctx == NULL) { PyErr_NoMemory(); return NULL; } /* Get the raw (binary) digest value */ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { return _setException(PyExc_ValueError); } digest_size = EVP_MD_CTX_size(temp_ctx); EVP_DigestFinal(temp_ctx, digest, NULL); EVP_MD_CTX_free(temp_ctx); return _Py_strhex((const char *)digest, digest_size); }
/* * Not really public interface, * but common routine called from both client and server. */ int gfs_digest_calculate_local(int fd, char *buffer, size_t buffer_size, const EVP_MD *md_type, EVP_MD_CTX *md_ctx, size_t *md_lenp, unsigned char *md_value, gfarm_off_t *filesizep) { int size, save_errno; gfarm_off_t off = 0; unsigned int len; if (lseek(fd, (off_t)0, 0) == -1) { save_errno = errno; gflog_debug(GFARM_MSG_1001020, "lseek() failed: %s", strerror(save_errno)); return (save_errno); } EVP_DigestInit(md_ctx, md_type); while ((size = read(fd, buffer, buffer_size)) > 0) { EVP_DigestUpdate(md_ctx, buffer, size); off += size; } EVP_DigestFinal(md_ctx, md_value, &len); *md_lenp = len; *filesizep = off; if (size == -1) { save_errno = errno; gflog_debug(GFARM_MSG_1001021, "read() failed: %s", strerror(save_errno)); return (save_errno); } return (0); }
static PyObject * EVP_digest(EVPobject *self, PyObject *unused) { unsigned char digest[EVP_MAX_MD_SIZE]; EVP_MD_CTX *temp_ctx; PyObject *retval; unsigned int digest_size; temp_ctx = EVP_MD_CTX_new(); if (temp_ctx == NULL) { PyErr_NoMemory(); return NULL; } if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { return _setException(PyExc_ValueError); } digest_size = EVP_MD_CTX_size(temp_ctx); EVP_DigestFinal(temp_ctx, digest, NULL); retval = PyBytes_FromStringAndSize((const char *)digest, digest_size); EVP_MD_CTX_free(temp_ctx); return retval; }
static void sl_digest (void){ SLang_BString_Type* data; /* we will give a slang string */ unsigned char output[EVP_MAX_MD_SIZE]; const EVP_MD *md; EVP_MD_CTX ctx; char* dtype; int dlen, hashlen; SLang_BString_Type *out; if (SLang_Num_Function_Args != 2 || SLang_pop_slstring(&dtype) == -1 ){ return;} md = EVP_get_digestbyname(dtype); if (!md){ SLang_verror(SL_UNDEFINED_NAME,"could not find digest %s",dtype); SLang_free_slstring(dtype); return; } if (SLang_pop_bstring(&data) == -1 ){ return; } unsigned char* idata = SLbstring_get_pointer (data,&dlen); EVP_MD_CTX_init(&ctx); EVP_DigestInit_ex(&ctx, md, NULL); EVP_DigestUpdate(&ctx, idata, dlen); EVP_DigestFinal(&ctx, output, &hashlen); out = SLbstring_create (output, hashlen); SLang_push_bstring(out); SLbstring_free(data); SLbstring_free(out); }
int ssh_dss_verify(DSA *key, u_char *signature, u_int signaturelen, u_char *data, u_int datalen) { DSA_SIG *sig; const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; unsigned char digest[EVP_MAX_MD_SIZE], *sigblob; unsigned int len, dlen; int ret; char *ptr; OpenSSL_add_all_digests(); if (key == NULL) { return -2; } ptr = signature; // step1 if (signaturelen == 0x28) { // workaround for SSH-2.0-2.0* and SSH-2.0-2.1* (2006.11.18 maya) ptr -= 4; } else { len = get_uint32_MSBfirst(ptr); ptr += 4; if (strncmp("ssh-dss", ptr, len) != 0) { return -3; } ptr += len; } // step2 len = get_uint32_MSBfirst(ptr); ptr += 4; sigblob = ptr; ptr += len; if (len != SIGBLOB_LEN) { return -4; } /* parse signature */ if ((sig = DSA_SIG_new()) == NULL) return -5; if ((sig->r = BN_new()) == NULL) return -6; if ((sig->s = BN_new()) == NULL) return -7; BN_bin2bn(sigblob, INTBLOB_LEN, sig->r); BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s); /* sha1 the data */ EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = DSA_do_verify(digest, dlen, sig, key); memset(digest, 'd', sizeof(digest)); DSA_SIG_free(sig); return ret; }
int ssh_ecdsa_verify(EC_KEY *key, ssh_keytype keytype, u_char *signature, u_int signaturelen, u_char *data, u_int datalen) { ECDSA_SIG *sig; const EVP_MD *evp_md; EVP_MD_CTX md; unsigned char digest[EVP_MAX_MD_SIZE], *sigblob; unsigned int len, dlen; int ret, nid = NID_undef; char *ptr; OpenSSL_add_all_digests(); if (key == NULL) { return -2; } ptr = signature; len = get_uint32_MSBfirst(ptr); ptr += 4; if (strncmp(get_ssh_keytype_name(keytype), ptr, len) != 0) { return -3; } ptr += len; len = get_uint32_MSBfirst(ptr); ptr += 4; sigblob = ptr; ptr += len; /* parse signature */ if ((sig = ECDSA_SIG_new()) == NULL) return -4; if ((sig->r = BN_new()) == NULL) return -5; if ((sig->s = BN_new()) == NULL) return -6; buffer_get_bignum2(&sigblob, sig->r); buffer_get_bignum2(&sigblob, sig->s); if (sigblob != ptr) { return -7; } /* hash the data */ nid = keytype_to_hash_nid(keytype); if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { return -8; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = ECDSA_do_verify(digest, dlen, sig, key); memset(digest, 'd', sizeof(digest)); ECDSA_SIG_free(sig); return ret; }
int ssh_rsa_verify(RSA *key, u_char *signature, u_int signaturelen, u_char *data, u_int datalen) { const EVP_MD *evp_md; EVP_MD_CTX md; // char *ktype; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen, modlen; // int rlen, ret, nid; int ret, nid; char *ptr; OpenSSL_add_all_digests(); if (key == NULL) { return -2; } if (BN_num_bits(key->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { return -3; } //debug_print(41, signature, signaturelen); ptr = signature; // step1 len = get_uint32_MSBfirst(ptr); ptr += 4; if (strncmp("ssh-rsa", ptr, len) != 0) { return -4; } ptr += len; // step2 len = get_uint32_MSBfirst(ptr); ptr += 4; sigblob = ptr; ptr += len; #if 0 rlen = get_uint32_MSBfirst(ptr); if (rlen != 0) { return -1; } #endif /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key); if (len > modlen) { return -5; } else if (len < modlen) { u_int diff = modlen - len; sigblob = realloc(sigblob, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } /* sha1 the data */ // nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; nid = NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { //error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); return -6; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); //free(sigblob); //debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }
BOOL generate_SSH2_keysign(Key *keypair, char **sigptr, int *siglen, char *data, int datalen) { buffer_t *msg = NULL; char *s; int ret; msg = buffer_init(); if (msg == NULL) { // TODO: error check return FALSE; } switch (keypair->type) { case KEY_RSA: // RSA { const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], *sig; u_int slen, dlen, len; int ok, nid = NID_sha1; // ダイジェスト値の計算 EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); slen = RSA_size(keypair->rsa); sig = malloc(slen); if (sig == NULL) goto error; // 電子署名を計算 ok = RSA_sign(nid, digest, dlen, sig, &len, keypair->rsa); memset(digest, 'd', sizeof(digest)); if (ok != 1) { // error free(sig); goto error; } // 署名のサイズがバッファより小さい場合、後ろへずらす。先頭はゼロで埋める。 if (len < slen) { u_int diff = slen - len; memmove(sig + diff, sig, len); memset(sig, 0, diff); } else if (len > slen) { free(sig); goto error; } else { // do nothing } s = get_sshname_from_key(keypair); buffer_put_string(msg, s, strlen(s)); buffer_append_length(msg, sig, slen); len = buffer_len(msg); // setting *siglen = len; *sigptr = malloc(len); if (*sigptr == NULL) { free(sig); goto error; } memcpy(*sigptr, buffer_ptr(msg), len); free(sig); break; } case KEY_DSA: // DSA { DSA_SIG *sig; const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; u_int rlen, slen, len, dlen; // ダイジェストの計算 EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); // DSA電子署名を計算 sig = DSA_do_sign(digest, dlen, keypair->dsa); memset(digest, 'd', sizeof(digest)); if (sig == NULL) { goto error; } // BIGNUMからバイナリ値への変換 rlen = BN_num_bytes(sig->r); slen = BN_num_bytes(sig->s); if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { DSA_SIG_free(sig); goto error; } memset(sigblob, 0, SIGBLOB_LEN); BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); DSA_SIG_free(sig); // setting s = get_sshname_from_key(keypair); buffer_put_string(msg, s, strlen(s)); buffer_append_length(msg, sigblob, sizeof(sigblob)); len = buffer_len(msg); // setting *siglen = len; *sigptr = malloc(len); if (*sigptr == NULL) { goto error; } memcpy(*sigptr, buffer_ptr(msg), len); break; } case KEY_ECDSA256: // ECDSA case KEY_ECDSA384: case KEY_ECDSA521: { ECDSA_SIG *sig; const EVP_MD *evp_md; EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE]; u_int len, dlen, nid; buffer_t *buf2 = NULL; nid = keytype_to_hash_nid(keypair->type); if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { goto error; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); sig = ECDSA_do_sign(digest, dlen, keypair->ecdsa); memset(digest, 'd', sizeof(digest)); if (sig == NULL) { goto error; } buf2 = buffer_init(); if (buf2 == NULL) { // TODO: error check goto error; } buffer_put_bignum2(buf2, sig->r); buffer_put_bignum2(buf2, sig->s); ECDSA_SIG_free(sig); s = get_sshname_from_key(keypair); buffer_put_string(msg, s, strlen(s)); buffer_put_string(msg, buffer_ptr(buf2), buffer_len(buf2)); buffer_free(buf2); len = buffer_len(msg); *siglen = len; *sigptr = malloc(len); if (*sigptr == NULL) { goto error; } memcpy(*sigptr, buffer_ptr(msg), len); break; } case KEY_ED25519: ret = ssh_ed25519_sign(keypair, sigptr, siglen, data, datalen); if (ret != 0) goto error; break; default: buffer_free(msg); return FALSE; break; } buffer_free(msg); return TRUE; error: buffer_free(msg); return FALSE; }
char * lcg_compute_checksum (const char *file, enum gfal_cksm_type cksmtype, char *errbuf, int errbufsz) { unsigned long cksm = 0; EVP_MD_CTX evpctx; int fd = -1; unsigned int nbread = 0; char buffer[GFAL_CKSM_BUFSIZE]; char checksum[2 * EVP_MAX_MD_SIZE + 1]; unsigned char cksm_raw[EVP_MAX_MD_SIZE + 1]; int cksmsize = 0; if (file == NULL || cksmtype == GFAL_CKSM_NONE) { gfal_errmsg (errbuf, errbufsz, GFAL_ERRLEVEL_ERROR, "[LCG-UTIL][compute_checksum][] Invalid arguments"); errno = EINVAL; return (NULL); } memset (checksum, 0, (2 * EVP_MAX_MD_SIZE + 1) * sizeof (char)); if (cksmtype == GFAL_CKSM_CRC32 || cksmtype == GFAL_CKSM_ADLER32) { zlib_handle = dlopen ("libz.so", RTLD_LAZY); if (zlib_handle == NULL) { gfal_errmsg (errbuf, errbufsz, GFAL_ERRLEVEL_ERROR, "[LCG-UTIL][compute_checksum][] CRC32/ADLER32 need zlib!"); errno = ELIBACC; return (NULL); } zlib_crc32 = (unsigned long (*) (unsigned long, const char *, unsigned int)) dlsym (zlib_handle, "crc32"); zlib_adler32 = (unsigned long (*) (unsigned long, const char *, unsigned int)) dlsym (zlib_handle, "adler32"); if (zlib_crc32 == NULL || zlib_adler32 == NULL) { gfal_errmsg (errbuf, errbufsz, GFAL_ERRLEVEL_ERROR, "[LCG-UTIL][compute_checksum][] invalid zlib library!"); errno = ELIBBAD; return (NULL); } } fd = gfal_open (file, O_RDONLY, 0); if (fd < 0) return (NULL); if (cksmtype == GFAL_CKSM_ADLER32) cksm = zlib_adler32 (0L, 0, 0); else if (cksmtype == GFAL_CKSM_CRC32) cksm = zlib_crc32 (0L, 0, 0); else { if (cksmtype == GFAL_CKSM_MD5) EVP_DigestInit (&evpctx, EVP_md5()); else EVP_DigestInit (&evpctx, EVP_sha1()); } while ((nbread = (unsigned int) gfal_read (fd, buffer, GFAL_CKSM_BUFSIZE)) > 0) { if (cksmtype == GFAL_CKSM_ADLER32) cksm = zlib_adler32 (cksm, buffer, nbread); else if (cksmtype == GFAL_CKSM_CRC32) cksm = zlib_crc32 (cksm, buffer, nbread); else EVP_DigestUpdate(&evpctx, buffer, (size_t) nbread); } gfal_close (fd); if (nbread < 0) return (NULL); if (cksmtype == GFAL_CKSM_ADLER32 || cksmtype == GFAL_CKSM_CRC32) { sprintf(checksum, "%08x", (unsigned int) cksm); } else { char *p; int i; EVP_DigestFinal (&evpctx, cksm_raw, &cksmsize); for (i = 0, p = checksum; i < cksmsize; ++i, p = p + 2) sprintf(p, "%02x", cksm_raw[i]); } return (strdup (checksum)); }
static int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *res, unsigned int *len) { EVP_DigestFinal(ctx, res, len); return 1; }
int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, const unsigned char *mHash, const EVP_MD *Hash, int sLen) { int i; int ret = 0; int hLen, maskedDBLen, MSBits, emLen; unsigned char *H, *salt = NULL, *p; EVP_MD_CTX ctx; hLen = EVP_MD_size(Hash); /* * Negative sLen has special meanings: * -1 sLen == hLen * -2 salt length is maximized * -N reserved */ if (sLen == -1) sLen = hLen; else if (sLen == -2) sLen = -2; else if (sLen < -2) { RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED); goto err; } MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; emLen = RSA_size(rsa); if (MSBits == 0) { *EM++ = 0; emLen--; } if (sLen == -2) { sLen = emLen - hLen - 2; } else if (emLen < (hLen + sLen + 2)) { RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); goto err; } if (sLen > 0) { salt = OPENSSL_malloc(sLen); if (!salt) { RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, ERR_R_MALLOC_FAILURE); goto err; } if (!RAND_bytes(salt, sLen)) goto err; } maskedDBLen = emLen - hLen - 1; H = EM + maskedDBLen; EVP_MD_CTX_init(&ctx); EVP_DigestInit_ex(&ctx, Hash, NULL); EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes); EVP_DigestUpdate(&ctx, mHash, hLen); if (sLen) EVP_DigestUpdate(&ctx, salt, sLen); EVP_DigestFinal(&ctx, H, NULL); EVP_MD_CTX_cleanup(&ctx); /* Generate dbMask in place then perform XOR on it */ PKCS1_MGF1(EM, maskedDBLen, H, hLen, Hash); p = EM; /* Initial PS XORs with all zeroes which is a NOP so just update * pointer. Note from a test above this value is guaranteed to * be non-negative. */ p += emLen - sLen - hLen - 2; *p++ ^= 0x1; if (sLen > 0) { for (i = 0; i < sLen; i++) *p++ ^= salt[i]; } if (MSBits) EM[0] &= 0xFF >> (8 - MSBits); /* H is already in place so just set final 0xbc */ EM[emLen - 1] = 0xbc; ret = 1; err: if (salt) OPENSSL_free(salt); return ret; }
_SCAPI_NOT_CONFIGURED #endif /* */ /* sc_hash(): a generic wrapper around whatever hashing package we are using. IN: hashtype - oid pointer to a hash type hashtypelen - length of oid pointer buf - u_char buffer to be hashed buf_len - integer length of buf data MAC_len - length of the passed MAC buffer size. OUT: MAC - pre-malloced space to store hash output. MAC_len - length of MAC output to the MAC buffer. Returns: SNMPERR_SUCCESS Success. SNMP_SC_GENERAL_FAILURE Any error. */ int sc_hash(oid *hashtype, size_t hashtypelen, u_char *buf, size_t buf_len, u_char *MAC, size_t *MAC_len) #if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) { int rval = SNMPERR_SUCCESS; #ifdef USE_OPENSSL EVP_MD *hash(void); HMAC_CTX *c = NULL; #endif DEBUGTRACE; if (hashtype == NULL || hashtypelen < 0 || buf == NULL || buf_len < 0 || MAC == NULL || MAC_len == NULL || (int)(*MAC_len) < sc_get_properlength(hashtype, hashtypelen)) return (SNMPERR_GENERR); #ifdef USE_OPENSSL /* * Determine transform type. */ c = malloc(sizeof(HMAC_CTX)); if (c == NULL) return (SNMPERR_GENERR); if (ISTRANSFORM(hashtype, HMACMD5Auth)) { EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_md5()); } else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_sha1()); } else { return(SNMPERR_GENERR); } EVP_DigestUpdate(&c->md_ctx, buf, buf_len); EVP_DigestFinal(&(c->md_ctx), MAC, MAC_len); free(c); return (rval); #else /* USE_INTERNAL_MD5 */ if (MDchecksum(buf, buf_len, MAC, *MAC_len)) { return SNMPERR_GENERR; } if (*MAC_len > 16) *MAC_len = 16; return SNMPERR_SUCCESS; #endif /* USE_OPENSSL */ }
/*******************************************************************-o-****** * generate_Ku * * Parameters: * *hashtype MIB OID for the transform type for hashing. * hashtype_len Length of OID value. * *P Pre-allocated bytes of passpharase. * pplen Length of passphrase. * *Ku Buffer to contain Ku. * *kulen Length of Ku buffer. * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_GENERR All errors. * * * Convert a passphrase into a master user key, Ku, according to the * algorithm given in RFC 2274 concerning the SNMPv3 User Security Model (USM) * as follows: * * Expand the passphrase to fill the passphrase buffer space, if necessary, * concatenation as many duplicates as possible of P to itself. If P is * larger than the buffer space, truncate it to fit. * * Then hash the result with the given hashtype transform. Return * the result as Ku. * * If successful, kulen contains the size of the hash written to Ku. * * NOTE Passphrases less than USM_LENGTH_P_MIN characters in length * cause an error to be returned. * (Punt this check to the cmdline apps? XXX) */ int generate_Ku( oid *hashtype, u_int hashtype_len, u_char *P, size_t pplen, u_char *Ku, size_t *kulen) #if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) { int rval = SNMPERR_SUCCESS, nbytes = USM_LENGTH_EXPANDED_PASSPHRASE; u_int i, pindex = 0; u_char buf[USM_LENGTH_KU_HASHBLOCK], *bufp; #ifdef USE_OPENSSL EVP_MD_CTX *ctx = malloc(sizeof(EVP_MD_CTX)); #else MDstruct MD; #endif /* * Sanity check. */ if ( !hashtype || !P || !Ku || !kulen || (*kulen<=0) || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) { QUITFUN(SNMPERR_GENERR, generate_Ku_quit); } if (pplen < USM_LENGTH_P_MIN) { #ifdef SNMP_TESTING_CODE snmp_log(LOG_WARNING, "Warning: passphrase chosen is below the length requiremnts of the USM.\n"); #else snmp_set_detail("Password length too short."); QUITFUN(SNMPERR_GENERR, generate_Ku_quit); #endif } /* * Setup for the transform type. */ #ifdef USE_OPENSSL if (ISTRANSFORM(hashtype, HMACMD5Auth)) EVP_DigestInit(ctx, EVP_md5()); else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) EVP_DigestInit(ctx, EVP_sha1()); else { free(ctx); return (SNMPERR_GENERR); } #else MDbegin(&MD); #endif /* USE_OPENSSL */ while (nbytes > 0) { bufp = buf; for (i = 0; i < USM_LENGTH_KU_HASHBLOCK; i++) { *bufp++ = P[pindex++ % pplen]; } #ifdef USE_OPENSSL EVP_DigestUpdate(ctx, buf, USM_LENGTH_KU_HASHBLOCK); #else if (MDupdate(&MD, buf, USM_LENGTH_KU_HASHBLOCK*8)) { rval = SNMPERR_USM_ENCRYPTIONERROR; goto md5_fin; } #endif /* USE_OPENSSL */ nbytes -= USM_LENGTH_KU_HASHBLOCK; } #ifdef USE_OPENSSL EVP_DigestFinal(ctx, (unsigned char *) Ku, (unsigned int *) kulen); /* what about free() */ #else if (MDupdate(&MD, buf, 0)) { rval = SNMPERR_USM_ENCRYPTIONERROR; goto md5_fin; } *kulen = sc_get_properlength(hashtype, hashtype_len); MDget(&MD, Ku, *kulen); md5_fin: memset(&MD, 0, sizeof(MD)); #endif /* USE_OPENSSL */ #ifdef SNMP_TESTING_CODE DEBUGMSGTL(("generate_Ku", "generating Ku (from %s): ", P)); for(i=0; i < *kulen; i++) DEBUGMSG(("generate_Ku", "%02x",Ku[i])); DEBUGMSG(("generate_Ku","\n")); #endif /* SNMP_TESTING_CODE */ generate_Ku_quit: memset(buf, 0, sizeof(buf)); #ifdef USE_OPENSSL free(ctx); #endif return rval; } /* end generate_Ku() */
/*++ * Function: Get_Server_conn * * Purpose: When a client login attempt is made, fetch a usable server * connection descriptor. This means that either we reuse an * existing ICD, or we open a new one. Hide that abstraction from * the caller... * * Parameters: ptr to username string * ptr to password string * const ptr to client hostname or IP string (for logging only) * in_port_t, client port number (for logging only) * unsigned char - flag to indicate that the client sent the * password as a string literal. * * Returns: ICD * on success * NULL on failure * * Authors: Dave McMurtrie <*****@*****.**> * * Credit: Major SSL additions by Ken Murchison <*****@*****.**> * *-- */ extern ICD_Struct *Get_Server_conn( char *Username, char *Password, const char *ClientAddr, in_port_t sin_port, unsigned char LiteralPasswd ) { char *fn = "Get_Server_conn()"; unsigned int HashIndex; ICC_Struct *HashEntry = NULL; char SendBuf[BUFSIZE]; unsigned int BufLen = BUFSIZE - 1; char md5pw[MD5_DIGEST_LENGTH]; char *tokenptr; char *endptr; char *last; ICC_Struct *ICC_Active; ICC_Struct *ICC_tptr; ITD_Struct Server; int rc; unsigned int Expiration; EVP_MD_CTX mdctx; int md_len; Expiration = PC_Struct.cache_expiration_time; memset( &Server, 0, sizeof Server ); /* need to md5 the passwd regardless, so do that now */ EVP_DigestInit(&mdctx, EVP_md5()); EVP_DigestUpdate(&mdctx, Password, strlen(Password)); EVP_DigestFinal(&mdctx, md5pw, &md_len); /* see if we have a reusable connection available */ ICC_Active = NULL; HashIndex = Hash( Username, HASH_TABLE_SIZE ); LockMutex( &mp ); /* * Now we just iterate through the linked list at this hash index until * we either find the string we're looking for or we find a NULL. */ for ( HashEntry = ICC_HashTable[ HashIndex ]; HashEntry; HashEntry = HashEntry->next ) { if ( ( strcmp( Username, HashEntry->username ) == 0 ) && ( HashEntry->logouttime > 1 ) ) { ICC_Active = HashEntry; /* * we found this username in our hash table. Need to know if * the password matches. */ if ( memcmp( md5pw, ICC_Active->hashedpw, sizeof md5pw ) ) { syslog( LOG_NOTICE, "%s: Unable to reuse server sd [%d] for user '%s' (%s:%d) because password doesn't match.", fn, ICC_Active->server_conn->sd, Username, ClientAddr, sin_port ); ICC_Active->logouttime = 1; } else { /* * We found a matching password on an inactive server socket. * We can use this guy. Before we release the mutex, set the * logouttime such that we mark this connection as "active" * again. */ ICC_Active->logouttime = 0; /* * The fact that we have this stored in a table as an open * server socket doesn't really mean that it's open. The * server could've closed it on us. * We need a speedy way to make sure this is still open. * We'll set the fd to non-blocking and try to read from it. * If we get a zero back, the connection is closed. If we get * EWOULDBLOCK (or some data) we know it's still open. If we * do read data, make sure we read all the data so we "drain" * any puss that may be left on this socket. */ fcntl( ICC_Active->server_conn->sd, F_SETFL, fcntl( ICC_Active->server_conn->sd, F_GETFL, 0) | O_NONBLOCK ); while ( ( rc = IMAP_Read( ICC_Active->server_conn, Server.ReadBuf, sizeof Server.ReadBuf ) ) > 0 ); if ( !rc ) { syslog(LOG_NOTICE, "%s: Unable to reuse server sd [%d] for user '%s' (%s:%d). Connection closed by server.", fn, ICC_Active->server_conn->sd, Username, ClientAddr, sin_port ); ICC_Active->logouttime = 1; continue; } if ( errno != EWOULDBLOCK ) { syslog(LOG_NOTICE, "%s: Unable to reuse server sd [%d] for user '%s' (%s:%d). IMAP_read() error: %s", fn, ICC_Active->server_conn->sd, Username, ClientAddr, sin_port, strerror( errno ) ); ICC_Active->logouttime = 1; continue; } fcntl( ICC_Active->server_conn->sd, F_SETFL, fcntl( ICC_Active->server_conn->sd, F_GETFL, 0) & ~O_NONBLOCK ); /* now release the mutex and return the sd to the caller */ UnLockMutex( &mp ); /* * We're reusing an existing server socket. There are a few * counters we have to deal with. */ IMAPCount->RetainedServerConnections--; IMAPCount->InUseServerConnections++; IMAPCount->TotalServerConnectionsReused++; if ( IMAPCount->InUseServerConnections > IMAPCount->PeakInUseServerConnections ) IMAPCount->PeakInUseServerConnections = IMAPCount->InUseServerConnections; syslog(LOG_INFO, "LOGIN: '******' (%s:%d) on existing sd [%d]", Username, ClientAddr, sin_port, ICC_Active->server_conn->sd ); return( ICC_Active->server_conn ); } } } UnLockMutex( &mp ); /* * We don't have an active connection for this user, or the password * didn't match. * Open a connection to the IMAP server so we can attempt to login */ Server.conn = ( ICD_Struct * ) malloc( sizeof ( ICD_Struct ) ); memset( Server.conn, 0, sizeof ( ICD_Struct ) ); Server.conn->sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( Server.conn->sd == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: Unable to open server socket: %s", Username, ClientAddr, sin_port, strerror( errno ) ); goto fail; } if ( PC_Struct.send_tcp_keepalives ) { int onoff = 1; setsockopt( Server.conn->sd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof onoff ); } if ( connect( Server.conn->sd, (struct sockaddr *)&ISD.srv, sizeof(ISD.srv) ) == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: Unable to connect to IMAP server: %s", Username, ClientAddr, sin_port, strerror( errno ) ); goto fail; } /* Read & throw away the banner line from the server */ if ( IMAP_Line_Read( &Server ) == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: No banner line received from IMAP server", Username, ClientAddr, sin_port ); goto fail; } /* * Do STARTTLS if necessary. */ #if HAVE_LIBSSL if ( PC_Struct.login_disabled ) { snprintf( SendBuf, BufLen, "S0001 STARTTLS\r\n" ); if ( IMAP_Write( Server.conn, SendBuf, strlen(SendBuf) ) == -1 ) { syslog(LOG_INFO, "STARTTLS failed: IMAP_Write() failed attempting to send STARTTLS command to IMAP server: %s", strerror( errno ) ); goto fail; } /* * Read the server response */ if ( ( rc = IMAP_Line_Read( &Server ) ) == -1 ) { syslog(LOG_INFO, "STARTTLS failed: No response from IMAP server after sending STARTTLS command" ); goto fail; } /* * Try to match up the tag in the server response to the client tag. */ endptr = Server.ReadBuf + rc; tokenptr = memtok( Server.ReadBuf, endptr, &last ); if ( !tokenptr ) { /* * no tokens found in server response? Not likely, but we still * have to check. */ syslog(LOG_INFO, "STARTTLS failed: server response to STARTTLS command contained no tokens." ); goto fail; } if ( memcmp( (const void *)tokenptr, (const void *)"S0001", strlen( tokenptr ) ) ) { /* * non-matching tag read back from the server... Lord knows what this * is, so we'll fail. */ syslog(LOG_INFO, "STARTTLS failed: server response to STARTTLS command contained non-matching tag." ); goto fail; } /* * Now that we've matched the tags up, see if the response was 'OK' */ tokenptr = memtok( NULL, endptr, &last ); if ( !tokenptr ) { /* again, not likely but we still have to check... */ syslog(LOG_INFO, "STARTTLS failed: Malformed server response to STARTTLS command" ); goto fail; } if ( memcmp( (const void *)tokenptr, "OK", 2 ) ) { /* * If the server sent back a "NO" or "BAD", we can look at the actual * server logs to figure out why. We don't have to break our ass here * putting the string back together just for the sake of logging. */ syslog(LOG_INFO, "STARTTLS failed: non-OK server response to STARTTLS command" ); goto fail; } Server.conn->tls = SSL_new( tls_ctx ); if ( Server.conn->tls == NULL ) { syslog(LOG_INFO, "STARTTLS failed: SSL_new() failed" ); goto fail; } SSL_clear( Server.conn->tls ); rc = SSL_set_fd( Server.conn->tls, Server.conn->sd ); if ( rc == 0 ) { syslog(LOG_INFO, "STARTTLS failed: SSL_set_fd() failed: %d", SSL_get_error( Server.conn->tls, rc ) ); goto fail; } SSL_set_connect_state( Server.conn->tls ); rc = SSL_connect( Server.conn->tls ); if ( rc <= 0 ) { syslog(LOG_INFO, "STARTTLS failed: SSL_connect() failed, %d: %s", SSL_get_error( Server.conn->tls, rc ), SSLerrmessage() ); goto fail; } /* XXX Should we grab the session id for later reuse? */ } #endif /* HAVE_LIBSSL */ /* * Send the login command off to the IMAP server. Have to treat a literal * password different. */ if ( LiteralPasswd ) { snprintf( SendBuf, BufLen, "A0001 LOGIN %s {%d}\r\n", Username, strlen( Password ) ); if ( IMAP_Write( Server.conn, SendBuf, strlen(SendBuf) ) == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: IMAP_Write() failed attempting to send LOGIN command to IMAP server: %s", Username, ClientAddr, sin_port, strerror( errno ) ); goto fail; } /* * the server response should be a go ahead */ if ( ( rc = IMAP_Line_Read( &Server ) ) == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: Failed to receive go-ahead from IMAP server after sending LOGIN command", Username, ClientAddr, sin_port ); goto fail; } if ( Server.ReadBuf[0] != '+' ) { syslog( LOG_INFO, "LOGIN: '******' (%s:%d) failed: bad response from server after sending string literal specifier", Username, ClientAddr, sin_port ); goto fail; } /* * now send the password */ snprintf( SendBuf, BufLen, "%s\r\n", Password ); if ( IMAP_Write( Server.conn, SendBuf, strlen( SendBuf ) ) == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: IMAP_Write() failed attempting to send literal password to IMAP server: %s", Username, ClientAddr, sin_port, strerror( errno ) ); goto fail; } } else { /* * just send the login command via normal means. */ snprintf( SendBuf, BufLen, "A0001 LOGIN %s %s\r\n", Username, Password ); if ( IMAP_Write( Server.conn, SendBuf, strlen(SendBuf) ) == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: IMAP_Write() failed attempting to send LOGIN command to IMAP server: %s", Username, ClientAddr, sin_port, strerror( errno ) ); goto fail; } } /* * Read the server response. From RFC 3501: * * A server MAY include a CAPABILITY response code in the tagged OK * response to a successful LOGIN command in order to send * capabilities automatically. It is unnecessary for a client to * send a separate CAPABILITY command if it recognizes these * automatic capabilities. * * We have to be ready for the possibility that this might be an * untagged response... In an ideal world, we'd want to pass the * untagged stuff back to the client. For now, since the RFC doesn't * mandate that behaviour, we're not going to since we don't have a client * socket descriptor to send it to. */ for ( ;; ) { if ( ( rc = IMAP_Line_Read( &Server ) ) == -1 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: No response from IMAP server after sending LOGIN command", Username, ClientAddr, sin_port ); goto fail; } if ( Server.ReadBuf[0] != '*' ) break; } /* * Try to match up the tag in the server response to the client tag. */ endptr = Server.ReadBuf + rc; tokenptr = memtok( Server.ReadBuf, endptr, &last ); if ( !tokenptr ) { /* * no tokens found in server response? Not likely, but we still * have to check. */ syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: server response to LOGIN command contained no tokens.", Username, ClientAddr, sin_port ); goto fail; } if ( memcmp( (const void *)tokenptr, (const void *)"A0001", strlen( tokenptr ) ) ) { /* * non-matching tag read back from the server... Lord knows what this * is, so we'll fail. */ syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: server response to LOGIN command contained non-matching tag.", Username, ClientAddr, sin_port ); goto fail; } /* * Now that we've matched the tags up, see if the response was 'OK' */ tokenptr = memtok( NULL, endptr, &last ); if ( !tokenptr ) { /* again, not likely but we still have to check... */ syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: Malformed server response to LOGIN command", Username, ClientAddr, sin_port ); goto fail; } if ( memcmp( (const void *)tokenptr, "OK", 2 ) ) { /* * If the server sent back a "NO" or "BAD", we can look at the actual * server logs to figure out why. We don't have to break our ass here * putting the string back together just for the sake of logging. */ syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: non-OK server response to LOGIN command", Username, ClientAddr, sin_port ); goto fail; } /* * put this in our used list and remove it from the free list */ for( ; ; ) { LockMutex( &mp ); if ( ICC_free->next ) { /* generate the hash index */ HashIndex = Hash( Username, HASH_TABLE_SIZE ); /* temporarily store the address of the next free structure */ ICC_tptr = ICC_free->next; /* * We want to add the newest "used" structure at the front of * the list at the hash index. */ ICC_free->next = ICC_HashTable[ HashIndex ]; ICC_HashTable[ HashIndex ] = ICC_free; /* * less typing and more readability, set an "active" pointer. */ ICC_Active = ICC_free; /* now point the free listhead to the next available free struct */ ICC_free = ICC_tptr; /* fill in the newest used (oxymoron?) structure */ strncpy( ICC_Active->username, Username, sizeof ICC_Active->username ); memcpy( ICC_Active->hashedpw, md5pw, sizeof ICC_Active->hashedpw ); ICC_Active->logouttime = 0; /* zero means, "it's active". */ ICC_Active->server_conn = Server.conn; UnLockMutex( &mp ); IMAPCount->InUseServerConnections++; IMAPCount->TotalServerConnectionsCreated++; if ( IMAPCount->InUseServerConnections > IMAPCount->PeakInUseServerConnections ) IMAPCount->PeakInUseServerConnections = IMAPCount->InUseServerConnections; syslog(LOG_INFO, "LOGIN: '******' (%s:%d) on new sd [%d]", Username, ClientAddr, sin_port, Server.conn->sd ); return( Server.conn ); } /* * There weren't any free ICC structs. Try to free one. Make sure * we unlock the mutex, since ICC_Recycle needs to obtain it. */ UnLockMutex( &mp ); Expiration = abs( Expiration / 2 ); /* * Eventually, we have to fail */ if ( Expiration <= 2 ) { syslog(LOG_INFO, "LOGIN: '******' (%s:%d) failed: Out of free ICC structs.", Username, ClientAddr, sin_port ); goto fail; } ICC_Recycle( Expiration ); } fail: #if HAVE_LIBSSL if ( Server.conn->tls ) { SSL_shutdown( Server.conn->tls ); SSL_free( Server.conn->tls ); } #endif close( Server.conn->sd ); free( Server.conn ); return( NULL ); }
// SHA-1(160bit)/SHA-256(256bit)を求める unsigned char *kex_dh_gex_hash(const EVP_MD *evp_md, char *client_version_string, char *server_version_string, char *ckexinit, int ckexinitlen, char *skexinit, int skexinitlen, u_char *serverhostkeyblob, int sbloblen, int kexgex_min, int kexgex_bits, int kexgex_max, BIGNUM *kexgex_p, BIGNUM *kexgex_g, BIGNUM *client_dh_pub, BIGNUM *server_dh_pub, BIGNUM *shared_secret, unsigned int *hashlen) { buffer_t *b; static unsigned char digest[EVP_MAX_MD_SIZE]; EVP_MD_CTX md; b = buffer_init(); buffer_put_string(b, client_version_string, strlen(client_version_string)); buffer_put_string(b, server_version_string, strlen(server_version_string)); /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ buffer_put_int(b, ckexinitlen+1); buffer_put_char(b, SSH2_MSG_KEXINIT); buffer_append(b, ckexinit, ckexinitlen); buffer_put_int(b, skexinitlen+1); buffer_put_char(b, SSH2_MSG_KEXINIT); buffer_append(b, skexinit, skexinitlen); buffer_put_string(b, serverhostkeyblob, sbloblen); // DH group sizeのビット数を加算する buffer_put_int(b, kexgex_min); buffer_put_int(b, kexgex_bits); buffer_put_int(b, kexgex_max); // DH鍵の素数と生成元を加算する buffer_put_bignum2(b, kexgex_p); buffer_put_bignum2(b, kexgex_g); buffer_put_bignum2(b, client_dh_pub); buffer_put_bignum2(b, server_dh_pub); buffer_put_bignum2(b, shared_secret); // yutaka //debug_print(38, buffer_ptr(b), buffer_len(b)); EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, buffer_ptr(b), buffer_len(b)); EVP_DigestFinal(&md, digest, NULL); buffer_free(b); //write_buffer_file(digest, EVP_MD_size(evp_md)); *hashlen = EVP_MD_size(evp_md); return digest; }
static int derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, BIGNUM *shared_secret, u_char **keyp) { Kex *kex = ssh->kex; struct sshbuf *b = NULL; EVP_MD_CTX md; char c = id; u_int have; u_char *digest = NULL; int r, mdsz; if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0) return SSH_ERR_INVALID_ARGUMENT; if ((digest = calloc(1, roundup(need, mdsz))) == NULL || (b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put_bignum2(b, shared_secret)) != 0) goto out; /* K1 = HASH(K || H || "A" || session_id) */ if (EVP_DigestInit(&md, kex->evp_md) != 1 || (!(ssh->compat & SSH_BUG_DERIVEKEY) && EVP_DigestUpdate(&md, sshbuf_ptr(b), sshbuf_len(b)) != 1) || EVP_DigestUpdate(&md, hash, hashlen) != 1 || EVP_DigestUpdate(&md, &c, 1) != 1 || EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len) != 1 || EVP_DigestFinal(&md, digest, NULL) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* * expand key: * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) * Key = K1 || K2 || ... || Kn */ for (have = mdsz; need > have; have += mdsz) { if (EVP_DigestInit(&md, kex->evp_md) != 1 || (!(ssh->compat & SSH_BUG_DERIVEKEY) && EVP_DigestUpdate(&md, sshbuf_ptr(b), sshbuf_len(b)) != 1) || EVP_DigestUpdate(&md, hash, hashlen) != 1 || EVP_DigestUpdate(&md, digest, have) != 1 || EVP_DigestFinal(&md, digest + have, NULL) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } } #ifdef DEBUG_KEX fprintf(stderr, "key '%c'== ", c); dump_digest("key", digest, need); #endif *keyp = digest; digest = NULL; r = 0; out: if (digest) free(digest); if (b) sshbuf_free(b); return r; }
char* key_fingerprint_raw(Key *k, enum fp_type dgst_type, int *dgst_raw_length) { const EVP_MD *md = NULL; EVP_MD_CTX ctx; char *blob = NULL; char *retval = NULL; int len = 0; int nlen, elen; RSA *rsa; *dgst_raw_length = 0; switch (dgst_type) { case SSH_FP_MD5: md = EVP_md5(); break; case SSH_FP_SHA1: md = EVP_sha1(); break; case SSH_FP_SHA256: md = EVP_sha256(); break; default: md = EVP_md5(); } switch (k->type) { case KEY_RSA1: rsa = make_key(NULL, k->bits, k->exp, k->mod); nlen = BN_num_bytes(rsa->n); elen = BN_num_bytes(rsa->e); len = nlen + elen; blob = malloc(len); if (blob == NULL) { // TODO: } BN_bn2bin(rsa->n, blob); BN_bn2bin(rsa->e, blob + nlen); RSA_free(rsa); break; case KEY_DSA: case KEY_RSA: case KEY_ECDSA256: case KEY_ECDSA384: case KEY_ECDSA521: case KEY_ED25519: key_to_blob(k, &blob, &len); break; case KEY_UNSPEC: return retval; break; default: //fatal("key_fingerprint_raw: bad key type %d", k->type); break; } if (blob != NULL) { retval = malloc(EVP_MAX_MD_SIZE); if (retval == NULL) { // TODO: } EVP_DigestInit(&ctx, md); EVP_DigestUpdate(&ctx, blob, len); EVP_DigestFinal(&ctx, retval, dgst_raw_length); memset(blob, 0, len); free(blob); } else { //fatal("key_fingerprint_raw: blob is null"); } return retval; }
int main(int argc, char *argv[]) { TSS_HCONTEXT hContext; TSS_RESULT result; TSS_HTPM hTPM; TSS_HPOLICY hPolicy; char *credential_filename = DEFAULT_CREDENTIAL_FILENAME; UINT32 nonceVerifierLength; BYTE *nonceVerifier; TSS_HDAA hDAA; TSS_DAA_CREDENTIAL *hDaaCredential; TSS_DAA_SIGN_DATA signData; TSS_DAA_SIGNATURE daaSignature; TSS_DAA_SELECTED_ATTRIB revealAttributes; char *szTpmPasswd = DEFAULT_OWN_PASSWD; char *message = NULL; BYTE **attributes = NULL; FILE *file; char *param; int i, length, rv; bi_ptr random = NULL; TSS_BOOL isCorrect; EVP_MD_CTX *mdctx; TSS_HKEY hKEY; init_tss_version( &signData); init_tss_version( &daaSignature); init_tss_version( &revealAttributes); i = 1; while( i < argc) { param = argv[ i]; if ( strcmp( param, "-m") == 0 || strcmp( param, "--message") == 0) { i++; if( i == argc) return print_usage( argv[0]); message = argv[i]; } else if( strcmp( param, "-cr") == 0 || strcmp( param, "--credential") == 0){ i++; if( i == argc) return print_usage( argv[0]); credential_filename = argv[i]; } else if( strcmp( param, "-pw") == 0 || strcmp( param, "--passwd") == 0){ i++; if( i == argc) return print_usage( argv[0]); szTpmPasswd = argv[i]; } else { fprintf(stderr, "%s:unrecognized option `%s'\n", argv[0], param); return print_usage( argv[0]); } i++; } bi_init( NULL); printf("Loading credential: %s ", credential_filename); file = fopen( credential_filename, "r"); if( (hDaaCredential = load_TSS_DAA_CREDENTIAL( file)) == 0) { LogError( "[test_join]: Error when loading \'%s\': %s\n", credential_filename, strerror( errno)); result = TSS_E_FAIL; goto out_close; } fclose( file); printf("Done\n"); // Create Context LogDebug("Create Context"); result = Tspi_Context_Create( &hContext ); if ( result != TSS_SUCCESS ) { LogError( "Tspi_Context_Create %d\n", result ); goto out; } // Connect to Context result = Tspi_Context_Connect( hContext, NULL ); if ( result != TSS_SUCCESS) goto out_close; printf("\nConnect to the context: %X\n", hContext); if( (result = Tspi_Context_GetTpmObject( hContext, &hTPM)) != TSS_SUCCESS) goto out_close; // Get the correct policy using the TPM ownership PASSWD if( (result = Tspi_GetPolicyObject( hTPM, TSS_POLICY_USAGE, &hPolicy)) != TSS_SUCCESS) goto out_close; if( (result = Tspi_Policy_SetSecret( hPolicy, TSS_SECRET_MODE_PLAIN, strlen( szTpmPasswd), szTpmPasswd)) != TSS_SUCCESS) goto out_close; LogDebug("Tspi_Policy_SetSecret hPolicy received;%d", hPolicy); //Create Object result = obj_daa_add( hContext, &hDAA); if (result != TSS_SUCCESS) { LogError("Tspi_Context_CreateObject:%d", result); Tspi_Context_Close(hContext); LogError("%s: %s", argv[0], err_string(result)); exit(result); } LogDebug("created DAA object:%X", hDAA); // TODO: verifier base name ?? result = Tspi_DAA_VerifyInit( hDAA, // in &nonceVerifierLength, // out &nonceVerifier, // out 0, //baseNameLength, // out NULL //baseName // out ); if (result != TSS_SUCCESS) goto out_close; LogDebug("Verify Init return nonceVerifier [%s]", dump_byte_array( nonceVerifierLength, nonceVerifier)); create_TSS_DAA_SELECTED_ATTRIB( &revealAttributes, 5, 0, 1, 1, 0, 0); mdctx = EVP_MD_CTX_create(); // create the TSS_DAA_SIGN_DATA struct // .selector: 0 -> payload contains a handle to an AIK // 1 -> payload contains a hashed message if( message != NULL) { signData.selector = TSS_FLAG_DAA_SIGN_MESSAGE_HASH; signData.payloadFlag = TSS_FLAG_DAA_SIGN_MESSAGE_HASH; EVP_DigestInit(mdctx, DAA_PARAM_get_message_digest()); EVP_DigestUpdate(mdctx, (BYTE *)message, strlen( message)); signData.payloadLength = EVP_MD_CTX_size(mdctx); signData.payload = (BYTE *)EVP_MD_CTX_create(); EVP_DigestFinal(mdctx, signData.payload, NULL); } else { signData.selector = TSS_FLAG_DAA_SIGN_IDENTITY_KEY; result = Tspi_Context_CreateObject( hContext, // in TSS_OBJECT_TYPE_RSAKEY, // in TSS_KEY_SIZE_2048, // in &hKEY // out ); if( result != TSS_SUCCESS) goto out_close; } result = Tspi_TPM_DAA_Sign( hDAA, // in hTPM, // in (TSS_HKEY)hDaaCredential, // in revealAttributes, // in 0, // verifierBaseNameLength, // in NULL, // verifierBaseName, // in nonceVerifierLength, // in nonceVerifier, // in signData, // in &daaSignature // out ); if (result != TSS_SUCCESS) goto out_close; LogDebug("TPM_DAA_Sign return daaSignature [%s]", dump_byte_array( nonceVerifierLength, nonceVerifier)); // generate attributes list but without copying the not revealed ones attributes = malloc( sizeof(BYTE *) * hDaaCredential->attributesLength); for( i=0; i < (int)(hDaaCredential->attributesLength); i++) { if( revealAttributes.indicesList[i]) { attributes[i] = (BYTE *)malloc( DAA_PARAM_SIZE_F_I / 8); memcpy( attributes[i], hDaaCredential->attributes[i], DAA_PARAM_SIZE_F_I / 8); } else { attributes[i] = NULL; } } result = Tspi_DAA_VerifySignature( hDAA, // in daaSignature, // in (TSS_HKEY)&(hDaaCredential->issuerPK), // in signData, // in hDaaCredential->attributesLength, // in attributes, // in nonceVerifierLength, // in nonceVerifier, // in 0, //baseNameLength, //in NULL, // in &isCorrect // out ); printf("Signature correct:%s\n", ( isCorrect ? "yes" : "no")); out_close: EVP_MD_CTX_destroy(mdctx); if( attributes != NULL) { for( i=0; i<(int)hDaaCredential->attributesLength; i++) { if( attributes[i] != NULL) free( attributes[i]); } free( attributes); } if( random != NULL) bi_free_ptr( random); Tspi_Context_FreeMemory( hContext, NULL ); Tspi_Context_Close( hContext ); out: bi_release(); LogDebug("THE END result=%d:%s",result, err_string( result) );; return result; }
int ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen, modlen; int rlen, ret, nid; if (key == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || key->rsa == NULL) { error("ssh_rsa_verify: no RSA key"); return -1; } if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); return -1; } buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_string(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { error("ssh_rsa_verify: cannot handle type %s", ktype); buffer_free(&b); xfree(ktype); return -1; } xfree(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("ssh_rsa_verify: remaining bytes in signature %d", rlen); xfree(sigblob); return -1; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { error("ssh_rsa_verify: len %u > modlen %u", len, modlen); xfree(sigblob); return -1; } else if (len < modlen) { u_int diff = modlen - len; debug("ssh_rsa_verify: add padding: modlen %u > len %u", modlen, len); sigblob = xrealloc(sigblob, 1, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); xfree(sigblob); return -1; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); xfree(sigblob); debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }
/*******************************************************************-o-****** * generate_Ku * * Parameters: * *hashtype MIB OID for the transform type for hashing. * hashtype_len Length of OID value. * *P Pre-allocated bytes of passpharase. * pplen Length of passphrase. * *Ku Buffer to contain Ku. * *kulen Length of Ku buffer. * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_GENERR All errors. * * * Convert a passphrase into a master user key, Ku, according to the * algorithm given in RFC 2274 concerning the SNMPv3 User Security Model (USM) * as follows: * * Expand the passphrase to fill the passphrase buffer space, if necessary, * concatenation as many duplicates as possible of P to itself. If P is * larger than the buffer space, truncate it to fit. * * Then hash the result with the given hashtype transform. Return * the result as Ku. * * If successful, kulen contains the size of the hash written to Ku. * * NOTE Passphrases less than USM_LENGTH_P_MIN characters in length * cause an error to be returned. * (Punt this check to the cmdline apps? XXX) */ int generate_Ku(const oid * hashtype, u_int hashtype_len, const u_char * P, size_t pplen, u_char * Ku, size_t * kulen) #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO) { int rval = SNMPERR_SUCCESS, nbytes = USM_LENGTH_EXPANDED_PASSPHRASE; #if !defined(NETSNMP_USE_OPENSSL) && \ defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_INTERNAL_CRYPTO) int ret; #endif u_int i, pindex = 0; u_char buf[USM_LENGTH_KU_HASHBLOCK], *bufp; #ifdef NETSNMP_USE_OPENSSL EVP_MD_CTX *ctx = NULL; #elif NETSNMP_USE_INTERNAL_CRYPTO SHA_CTX csha1; MD5_CTX cmd5; char cryptotype = 0; #define TYPE_MD5 1 #define TYPE_SHA1 2 #else MDstruct MD; #endif /* * Sanity check. */ if (!hashtype || !P || !Ku || !kulen || (*kulen <= 0) || (hashtype_len != USM_LENGTH_OID_TRANSFORM)) { QUITFUN(SNMPERR_GENERR, generate_Ku_quit); } if (pplen < USM_LENGTH_P_MIN) { snmp_log(LOG_ERR, "Error: passphrase chosen is below the length " "requirements of the USM (min=%d).\n",USM_LENGTH_P_MIN); snmp_set_detail("The supplied password length is too short."); QUITFUN(SNMPERR_GENERR, generate_Ku_quit); } /* * Setup for the transform type. */ #ifdef NETSNMP_USE_OPENSSL #ifdef HAVE_EVP_MD_CTX_CREATE ctx = EVP_MD_CTX_create(); #else ctx = malloc(sizeof(*ctx)); EVP_MD_CTX_init(ctx); #endif #ifndef NETSNMP_DISABLE_MD5 if (ISTRANSFORM(hashtype, HMACMD5Auth)) EVP_DigestInit(ctx, EVP_md5()); else #endif if (ISTRANSFORM(hashtype, HMACSHA1Auth)) EVP_DigestInit(ctx, EVP_sha1()); else QUITFUN(SNMPERR_GENERR, generate_Ku_quit); #elif NETSNMP_USE_INTERNAL_CRYPTO #ifndef NETSNMP_DISABLE_MD5 if (ISTRANSFORM(hashtype, HMACMD5Auth)) { MD5_Init(&cmd5); cryptotype = TYPE_MD5; } else #endif if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { SHA1_Init(&csha1); cryptotype = TYPE_SHA1; } else { return (SNMPERR_GENERR); } #else MDbegin(&MD); #endif /* NETSNMP_USE_OPENSSL */ while (nbytes > 0) { bufp = buf; for (i = 0; i < USM_LENGTH_KU_HASHBLOCK; i++) { *bufp++ = P[pindex++ % pplen]; } #ifdef NETSNMP_USE_OPENSSL EVP_DigestUpdate(ctx, buf, USM_LENGTH_KU_HASHBLOCK); #elif NETSNMP_USE_INTERNAL_CRYPTO if (TYPE_SHA1 == cryptotype) { rval = !SHA1_Update(&csha1, buf, USM_LENGTH_KU_HASHBLOCK); } else { rval = !MD5_Update(&cmd5, buf, USM_LENGTH_KU_HASHBLOCK); } if (rval != 0) { return SNMPERR_USM_ENCRYPTIONERROR; } #elif NETSNMP_USE_INTERNAL_MD5 if (MDupdate(&MD, buf, USM_LENGTH_KU_HASHBLOCK * 8)) { rval = SNMPERR_USM_ENCRYPTIONERROR; goto md5_fin; } #endif /* NETSNMP_USE_OPENSSL */ nbytes -= USM_LENGTH_KU_HASHBLOCK; } #ifdef NETSNMP_USE_OPENSSL { unsigned int tmp_len; tmp_len = *kulen; EVP_DigestFinal(ctx, (unsigned char *) Ku, &tmp_len); *kulen = tmp_len; /* * what about free() */ } #elif NETSNMP_USE_INTERNAL_CRYPTO if (TYPE_SHA1 == cryptotype) { SHA1_Final(Ku, &csha1); } else { MD5_Final(Ku, &cmd5); } ret = sc_get_properlength(hashtype, hashtype_len); if (ret == SNMPERR_GENERR) return SNMPERR_GENERR; *kulen = ret; #elif NETSNMP_USE_INTERNAL_MD5 if (MDupdate(&MD, buf, 0)) { rval = SNMPERR_USM_ENCRYPTIONERROR; goto md5_fin; } ret = sc_get_properlength(hashtype, hashtype_len); if (ret == SNMPERR_GENERR) return SNMPERR_GENERR; *kulen = ret; MDget(&MD, Ku, *kulen); md5_fin: memset(&MD, 0, sizeof(MD)); #endif /* NETSNMP_USE_INTERNAL_MD5 */ #ifdef NETSNMP_ENABLE_TESTING_CODE DEBUGMSGTL(("generate_Ku", "generating Ku (from %s): ", P)); for (i = 0; i < *kulen; i++) DEBUGMSG(("generate_Ku", "%02x", Ku[i])); DEBUGMSG(("generate_Ku", "\n")); #endif /* NETSNMP_ENABLE_TESTING_CODE */ generate_Ku_quit: memset(buf, 0, sizeof(buf)); #ifdef NETSNMP_USE_OPENSSL if (ctx) { #ifdef HAVE_EVP_MD_CTX_DESTROY EVP_MD_CTX_destroy(ctx); #else EVP_MD_CTX_cleanup(ctx); free(ctx); #endif } #endif return rval; } /* end generate_Ku() */
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { const EVP_MD *evp_md; EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], *sig; u_int slen, dlen, len; int ok, nid; Buffer b; if (key == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || key->rsa == NULL) { error("ssh_rsa_sign: no RSA key"); return -1; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); return -1; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); slen = RSA_size(key->rsa); sig = xmalloc(slen); ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); memset(digest, 'd', sizeof(digest)); if (ok != 1) { int ecode = ERR_get_error(); error("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL)); xfree(sig); return -1; } if (len < slen) { u_int diff = slen - len; debug("slen %u > len %u", slen, len); memmove(sig + diff, sig, len); memset(sig, 0, diff); } else if (len > slen) { error("ssh_rsa_sign: slen %u slen2 %u", slen, len); xfree(sig); return -1; } /* encode signature */ buffer_init(&b); buffer_put_cstring(&b, "ssh-rsa"); buffer_put_string(&b, sig, slen); len = buffer_len(&b); if (lenp != NULL) *lenp = len; if (sigp != NULL) { *sigp = xmalloc(len); memcpy(*sigp, buffer_ptr(&b), len); } buffer_free(&b); memset(sig, 's', slen); xfree(sig); return 0; }
static int sb_verify_image_header(struct sb_image_ctx *ictx, FILE *fp, long fsize) { /* Verify static fields in the image header. */ struct sb_boot_image_header *hdr = &ictx->payload; const char *stat[2] = { "[PASS]", "[FAIL]" }; struct tm tm; int sz, ret = 0; unsigned char digest[20]; EVP_MD_CTX md_ctx; unsigned long size; /* Start image-wide crypto. */ EVP_MD_CTX_init(&ictx->md_ctx); EVP_DigestInit(&ictx->md_ctx, EVP_sha1()); soprintf(ictx, "---------- Verifying SB Image Header ----------\n"); size = fread(&ictx->payload, 1, sizeof(ictx->payload), fp); if (size != sizeof(ictx->payload)) { fprintf(stderr, "ERR: SB image header too short!\n"); return -EINVAL; } /* Compute header digest. */ EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha1()); EVP_DigestUpdate(&md_ctx, hdr->signature1, sizeof(struct sb_boot_image_header) - sizeof(hdr->digest)); EVP_DigestFinal(&md_ctx, digest, NULL); sb_aes_init(ictx, NULL, 1); sb_encrypt_sb_header(ictx); if (memcmp(digest, hdr->digest, 20)) ret = -EINVAL; soprintf(ictx, "%s Image header checksum: %s\n", stat[!!ret], ret ? "BAD" : "OK"); if (ret) return ret; if (memcmp(hdr->signature1, "STMP", 4) || memcmp(hdr->signature2, "sgtl", 4)) ret = -EINVAL; soprintf(ictx, "%s Signatures: '%.4s' '%.4s'\n", stat[!!ret], hdr->signature1, hdr->signature2); if (ret) return ret; if ((hdr->major_version != SB_VERSION_MAJOR) || ((hdr->minor_version != 1) && (hdr->minor_version != 2))) ret = -EINVAL; soprintf(ictx, "%s Image version: v%i.%i\n", stat[!!ret], hdr->major_version, hdr->minor_version); if (ret) return ret; ret = sb_get_time(hdr->timestamp_us / 1000000, &tm); soprintf(ictx, "%s Creation time: %02i:%02i:%02i %02i/%02i/%04i\n", stat[!!ret], tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mday, tm.tm_mon, tm.tm_year + 2000); if (ret) return ret; soprintf(ictx, "%s Product version: %x.%x.%x\n", stat[0], ntohs(hdr->product_version.major), ntohs(hdr->product_version.minor), ntohs(hdr->product_version.revision)); soprintf(ictx, "%s Component version: %x.%x.%x\n", stat[0], ntohs(hdr->component_version.major), ntohs(hdr->component_version.minor), ntohs(hdr->component_version.revision)); if (hdr->flags & ~SB_IMAGE_FLAGS_MASK) ret = -EINVAL; soprintf(ictx, "%s Image flags: %s\n", stat[!!ret], hdr->flags & SB_IMAGE_FLAG_DISPLAY_PROGRESS ? "Display_progress" : ""); if (ret) return ret; if (hdr->drive_tag != 0) ret = -EINVAL; soprintf(ictx, "%s Drive tag: %i\n", stat[!!ret], hdr->drive_tag); if (ret) return ret; sz = sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE; if (hdr->header_blocks != sz) ret = -EINVAL; soprintf(ictx, "%s Image header size (blocks): %i\n", stat[!!ret], hdr->header_blocks); if (ret) return ret; sz = sizeof(struct sb_sections_header) / SB_BLOCK_SIZE; if (hdr->section_header_size != sz) ret = -EINVAL; soprintf(ictx, "%s Section header size (blocks): %i\n", stat[!!ret], hdr->section_header_size); if (ret) return ret; soprintf(ictx, "%s Sections count: %i\n", stat[!!ret], hdr->section_count); soprintf(ictx, "%s First bootable section %i\n", stat[!!ret], hdr->first_boot_section_id); if (hdr->image_blocks != fsize / SB_BLOCK_SIZE) ret = -EINVAL; soprintf(ictx, "%s Image size (blocks): %i\n", stat[!!ret], hdr->image_blocks); if (ret) return ret; sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count; if (hdr->key_dictionary_block != sz) ret = -EINVAL; soprintf(ictx, "%s Key dict offset (blocks): %i\n", stat[!!ret], hdr->key_dictionary_block); if (ret) return ret; if (hdr->key_count != 1) ret = -EINVAL; soprintf(ictx, "%s Number of encryption keys: %i\n", stat[!!ret], hdr->key_count); if (ret) return ret; sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count; sz += hdr->key_count * sizeof(struct sb_key_dictionary_key) / SB_BLOCK_SIZE; if (hdr->first_boot_tag_block != (unsigned)sz) ret = -EINVAL; soprintf(ictx, "%s First TAG block (blocks): %i\n", stat[!!ret], hdr->first_boot_tag_block); if (ret) return ret; return 0; }
/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ static DECLCALLBACK(void) rtCrDigestOsslEvp_Final(void *pvState, uint8_t *pbHash) { unsigned int cbHash = EVP_MAX_MD_SIZE; EVP_DigestFinal((EVP_MD_CTX *)pvState, (unsigned char *)pbHash, &cbHash); }
int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, const EVP_MD *Hash, const unsigned char *EM, int sLen) { int i; int ret = 0; int hLen, maskedDBLen, MSBits, emLen; const unsigned char *H; unsigned char *DB = NULL; EVP_MD_CTX ctx; unsigned char H_[EVP_MAX_MD_SIZE]; hLen = EVP_MD_size(Hash); /* * Negative sLen has special meanings: * -1 sLen == hLen * -2 salt length is autorecovered from signature * -N reserved */ if (sLen == -1) sLen = hLen; else if (sLen == -2) sLen = -2; else if (sLen < -2) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED); goto err; } MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; emLen = RSA_size(rsa); if (EM[0] & (0xFF << MSBits)) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_FIRST_OCTET_INVALID); goto err; } if (MSBits == 0) { EM++; emLen--; } if (emLen < (hLen + sLen + 2)) /* sLen can be small negative */ { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_DATA_TOO_LARGE); goto err; } if (EM[emLen - 1] != 0xbc) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_LAST_OCTET_INVALID); goto err; } maskedDBLen = emLen - hLen - 1; H = EM + maskedDBLen; DB = OPENSSL_malloc(maskedDBLen); if (!DB) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, ERR_R_MALLOC_FAILURE); goto err; } PKCS1_MGF1(DB, maskedDBLen, H, hLen, Hash); for (i = 0; i < maskedDBLen; i++) DB[i] ^= EM[i]; if (MSBits) DB[0] &= 0xFF >> (8 - MSBits); for (i = 0; DB[i] == 0 && i < (maskedDBLen-1); i++) ; if (DB[i++] != 0x1) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_RECOVERY_FAILED); goto err; } if (sLen >= 0 && (maskedDBLen - i) != sLen) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED); goto err; } EVP_MD_CTX_init(&ctx); EVP_DigestInit_ex(&ctx, Hash, NULL); EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes); EVP_DigestUpdate(&ctx, mHash, hLen); if (maskedDBLen - i) EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i); EVP_DigestFinal(&ctx, H_, NULL); EVP_MD_CTX_cleanup(&ctx); if (memcmp(H_, H, hLen)) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_BAD_SIGNATURE); ret = 0; } else ret = 1; err: if (DB) OPENSSL_free(DB); return ret; }
static int sb_encrypt_image(struct sb_image_ctx *ictx) { /* Start image-wide crypto. */ EVP_MD_CTX_init(&ictx->md_ctx); EVP_DigestInit(&ictx->md_ctx, EVP_sha1()); /* * SB image header. */ sb_aes_init(ictx, NULL, 1); sb_encrypt_sb_header(ictx); /* * SB sections header. */ sb_encrypt_sb_sections_header(ictx); /* * Key dictionary. */ sb_aes_reinit(ictx, 1); sb_encrypt_key_dictionary_key(ictx); /* * Section tags. */ struct sb_cmd_ctx *cctx; struct sb_command *ccmd; struct sb_section_ctx *sctx = ictx->sect_head; while (sctx) { cctx = sctx->cmd_head; sb_aes_reinit(ictx, 1); while (cctx) { ccmd = &cctx->payload; sb_encrypt_tag(ictx, cctx); if (ccmd->header.tag == ROM_TAG_CMD) { sb_aes_reinit(ictx, 1); } else if (ccmd->header.tag == ROM_LOAD_CMD) { sb_aes_crypt(ictx, cctx->data, cctx->data, cctx->length); EVP_DigestUpdate(&ictx->md_ctx, cctx->data, cctx->length); } cctx = cctx->cmd; } sctx = sctx->sect; }; /* * Dump the SHA1 of the whole image. */ sb_aes_reinit(ictx, 1); EVP_DigestFinal(&ictx->md_ctx, ictx->digest, NULL); sb_aes_crypt(ictx, ictx->digest, ictx->digest, sizeof(ictx->digest)); /* Stop the encryption session. */ sb_aes_deinit(&ictx->cipher_ctx); return 0; }