static mp_int *ecdsa_signing_exponent_from_data( const struct ec_curve *curve, const struct ecsign_extra *extra, ptrlen data) { /* Hash the data being signed. */ unsigned char hash[MAX_HASH_LEN]; ssh_hash *h = ssh_hash_new(extra->hash); put_datapl(h, data); ssh_hash_final(h, hash); /* * Take the leftmost b bits of the hash of the signed data (where * b is the number of bits in order(G)), interpreted big-endian. */ mp_int *z = mp_from_bytes_be(make_ptrlen(hash, extra->hash->hlen)); size_t zbits = mp_get_nbits(z); size_t nbits = mp_get_nbits(curve->w.G_order); size_t shift = zbits - nbits; /* Bound the shift count below at 0, using bit twiddling to avoid * a conditional branch */ shift &= ~-(shift >> (CHAR_BIT * sizeof(size_t) - 1)); mp_int *toret = mp_rshift_safe(z, shift); mp_free(z); return toret; }
static void oaep_mask(const ssh_hashalg *h, void *seed, int seedlen, void *vdata, int datalen) { unsigned char *data = (unsigned char *)vdata; unsigned count = 0; while (datalen > 0) { int i, max = (datalen > h->hlen ? h->hlen : datalen); ssh_hash *s; unsigned char hash[MAX_HASH_LEN]; assert(h->hlen <= MAX_HASH_LEN); s = ssh_hash_new(h); put_data(s, seed, seedlen); put_uint32(s, count); ssh_hash_final(s, hash); count++; for (i = 0; i < max; i++) data[i] ^= hash[i]; data += max; datalen -= max; } }
/* * Generate a fingerprint string for the key. Compatible with the * OpenSSH fingerprint code. */ char *rsa_ssh1_fingerprint(RSAKey *key) { unsigned char digest[16]; strbuf *out; int i; /* * The hash preimage for SSH-1 key fingerprinting consists of the * modulus and exponent _without_ any preceding length field - * just the minimum number of bytes to represent each integer, * stored big-endian, concatenated with no marker at the division * between them. */ ssh_hash *hash = ssh_hash_new(&ssh_md5); for (size_t i = (mp_get_nbits(key->modulus) + 7) / 8; i-- > 0 ;) put_byte(hash, mp_get_byte(key->modulus, i)); for (size_t i = (mp_get_nbits(key->exponent) + 7) / 8; i-- > 0 ;) put_byte(hash, mp_get_byte(key->exponent, i)); ssh_hash_final(hash, digest); out = strbuf_new(); strbuf_catf(out, "%d ", mp_get_nbits(key->modulus)); for (i = 0; i < 16; i++) strbuf_catf(out, "%s%02x", i ? ":" : "", digest[i]); if (key->comment) strbuf_catf(out, " %s", key->comment); return strbuf_to_str(out); }
Boolean ssh_tls_ssl_prf(const unsigned char *secret, int secret_len, const unsigned char *random_1, int random_1_len, const unsigned char *random_2, int random_2_len, unsigned char *return_buf, int return_len) { unsigned char label; int i, j; SshHash md5, sha1; unsigned char sha_digest[20]; SSH_ASSERT(return_len % 16 == 0); SSH_ASSERT(return_len < 400); if (ssh_hash_allocate("md5", &md5) != SSH_CRYPTO_OK) return FALSE; if (ssh_hash_allocate("sha1", &sha1) != SSH_CRYPTO_OK) return FALSE; for (i = 1, label = 'A'; return_len > 0; i++, label++, return_buf += 16, return_len -= 16) { ssh_hash_reset(sha1); for (j = 0; j < i; j++) ssh_hash_update(sha1, &label, 1); ssh_hash_update(sha1, secret, secret_len); ssh_hash_update(sha1, random_1, random_1_len); ssh_hash_update(sha1, random_2, random_2_len); if (ssh_hash_final(sha1, sha_digest) != SSH_CRYPTO_OK) return FALSE; ssh_hash_reset(md5); ssh_hash_update(md5, secret, secret_len); ssh_hash_update(md5, sha_digest, 20); if (ssh_hash_final(md5, return_buf) != SSH_CRYPTO_OK) return FALSE; } ssh_hash_free(md5); ssh_hash_free(sha1); return TRUE; }
SshCryptoStatus ssh_hash_of_buffer(const char *type, const void *buf, size_t len, unsigned char *digest) { SshHash hash; SshCryptoStatus status; if ((status = ssh_hash_allocate(type, &hash)) != SSH_CRYPTO_OK) return status; ssh_hash_update(hash, buf, len); status = ssh_hash_final(hash, digest); ssh_hash_free(hash); return status; }
static mp_int *eddsa_signing_exponent_from_data( struct eddsa_key *ek, const struct ecsign_extra *extra, ptrlen r_encoded, ptrlen data) { /* Hash (r || public key || message) */ unsigned char hash[MAX_HASH_LEN]; ssh_hash *h = ssh_hash_new(extra->hash); put_datapl(h, r_encoded); put_epoint(h, ek->publicKey, ek->curve, true); /* omit string header */ put_datapl(h, data); ssh_hash_final(h, hash); /* Convert to an integer */ mp_int *toret = mp_from_bytes_le(make_ptrlen(hash, extra->hash->hlen)); smemclr(hash, extra->hash->hlen); return toret; }
void ssh_pm_ike_id_hash(SshPm pm, unsigned char hash[SSH_ENGINE_PEER_ID_SIZE], SshIkev2PayloadID id) { unsigned char digest[SSH_MAX_HASH_DIGEST_LENGTH]; ssh_hash_reset(pm->hash); ssh_hash_update(pm->hash, (unsigned char *) &id->id_type, sizeof(id->id_type)); ssh_hash_update(pm->hash, id->id_data, id->id_data_size); memset(digest, 0, SSH_MAX_HASH_DIGEST_LENGTH); if (ssh_hash_final(pm->hash, digest) != SSH_CRYPTO_OK) SSH_DEBUG(SSH_D_ERROR, ("Hash failed")); /* Use the first bytes of the digest as the hash value. */ SSH_ASSERT(SSH_ENGINE_PEER_ID_SIZE <= SSH_MAX_HASH_DIGEST_LENGTH); memcpy(hash, digest, SSH_ENGINE_PEER_ID_SIZE); }
void bcrypt_genblock(int counter, const unsigned char hashed_passphrase[64], const unsigned char *salt, int saltbytes, unsigned char output[32]) { unsigned char hashed_salt[64]; /* Hash the input salt with the counter value optionally suffixed * to get our real 32-byte salt */ ssh_hash *h = ssh_hash_new(&ssh_sha512); put_data(h, salt, saltbytes); if (counter) put_uint32(h, counter); ssh_hash_final(h, hashed_salt); bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output); smemclr(&hashed_salt, sizeof(hashed_salt)); }
int main(int argc, char *argv[]) { SshHash hash; unsigned char buf[16]; int i, j; if (ssh_crypto_library_initialize() != SSH_CRYPTO_OK) ssh_fatal("Could not initialize the crypto library."); if (ssh_hash_allocate("md5", &hash) != SSH_CRYPTO_OK) { fprintf(stderr, "could not allocate MD5 hash\n"); exit(1); } for (i = 1; i < argc; i++) { ssh_hash_reset(hash); ssh_hash_update(hash, argv[i], strlen(argv[i])); if (ssh_hash_final(hash, buf) != SSH_CRYPTO_OK) { fprintf(stderr, "could not compute MD5 hash digest\n"); exit(1); } printf("\ {\"%s\",\n\ \"", argv[i]); for (j = 0; j < sizeof(buf); j++) printf("\\x%02x", buf[j]); printf("\", %d , %d,\n\ 0, 0, 0, 0},\n", sizeof(buf), sizeof(buf)); } return 0; }
EdwardsPoint *eddsa_public(mp_int *private_key, const ssh_keyalg *alg) { const struct ecsign_extra *extra = (const struct ecsign_extra *)alg->extra; struct ec_curve *curve = extra->curve(); assert(curve->type == EC_EDWARDS); ssh_hash *h = ssh_hash_new(extra->hash); for (size_t i = 0; i < curve->fieldBytes; ++i) put_byte(h, mp_get_byte(private_key, i)); unsigned char hash[MAX_HASH_LEN]; ssh_hash_final(h, hash); mp_int *exponent = eddsa_exponent_from_hash( make_ptrlen(hash, extra->hash->hlen), curve); EdwardsPoint *toret = ecc_edwards_multiply(curve->e.G, exponent); mp_free(exponent); return toret; }
static unsigned char *rsa_pkcs1_signature_string( size_t nbytes, const ssh_hashalg *halg, ptrlen data) { size_t fixed_parts = rsa_pkcs1_length_of_fixed_parts(halg); assert(nbytes >= fixed_parts); size_t padding = nbytes - fixed_parts; ptrlen asn1_prefix = rsa_pkcs1_prefix_for_hash(halg); unsigned char *bytes = snewn(nbytes, unsigned char); bytes[0] = 0; bytes[1] = 1; memset(bytes + 2, 0xFF, padding); memcpy(bytes + 2 + padding, asn1_prefix.ptr, asn1_prefix.len); ssh_hash *h = ssh_hash_new(halg); put_datapl(h, data); ssh_hash_final(h, bytes + 2 + padding + asn1_prefix.len); return bytes; }
static void eddsa_sign(ssh_key *key, ptrlen data, unsigned flags, BinarySink *bs) { struct eddsa_key *ek = container_of(key, struct eddsa_key, sshk); const struct ecsign_extra *extra = (const struct ecsign_extra *)ek->sshk.vt->extra; assert(ek->privateKey); /* * EdDSA prescribes a specific method of generating the random * nonce integer for the signature. (A verifier can't tell * whether you followed that method, but it's important to * follow it anyway, because test vectors will want a specific * signature for a given message, and because this preserves * determinism of signatures even if the same signature were * made twice by different software.) */ /* * First, we hash the private key integer (bare, little-endian) * into a hash generating 2*fieldBytes of output. */ unsigned char hash[MAX_HASH_LEN]; ssh_hash *h = ssh_hash_new(extra->hash); for (size_t i = 0; i < ek->curve->fieldBytes; ++i) put_byte(h, mp_get_byte(ek->privateKey, i)); ssh_hash_final(h, hash); /* * The first half of the output hash is converted into an * integer a, by the standard EdDSA transformation. */ mp_int *a = eddsa_exponent_from_hash( make_ptrlen(hash, ek->curve->fieldBytes), ek->curve); /* * The second half of the hash of the private key is hashed again * with the message to be signed, and used as an exponent to * generate the signature point r. */ h = ssh_hash_new(extra->hash); put_data(h, hash + ek->curve->fieldBytes, extra->hash->hlen - ek->curve->fieldBytes); put_datapl(h, data); ssh_hash_final(h, hash); mp_int *log_r_unreduced = mp_from_bytes_le( make_ptrlen(hash, extra->hash->hlen)); mp_int *log_r = mp_mod(log_r_unreduced, ek->curve->e.G_order); mp_free(log_r_unreduced); EdwardsPoint *r = ecc_edwards_multiply(ek->curve->e.G, log_r); /* * Encode r now, because we'll need its encoding for the next * hashing step as well as to write into the actual signature. */ strbuf *r_enc = strbuf_new(); put_epoint(r_enc, r, ek->curve, true); /* omit string header */ ecc_edwards_point_free(r); /* * Compute the hash of (r || public key || message) just as * eddsa_verify does. */ mp_int *H = eddsa_signing_exponent_from_data( ek, extra, ptrlen_from_strbuf(r_enc), data); /* And then s = (log(r) + H*a) mod order(G). */ mp_int *Ha = mp_modmul(H, a, ek->curve->e.G_order); mp_int *s = mp_modadd(log_r, Ha, ek->curve->e.G_order); mp_free(H); mp_free(a); mp_free(Ha); mp_free(log_r); /* Format the output */ put_stringz(bs, ek->sshk.vt->ssh_id); put_uint32(bs, r_enc->len + ek->curve->fieldBytes); put_data(bs, r_enc->u, r_enc->len); strbuf_free(r_enc); for (size_t i = 0; i < ek->curve->fieldBytes; ++i) put_byte(bs, mp_get_byte(s, i)); mp_free(s); }
SshCryptoStatus ssh_rsa_oaep_encode_with_mgf1(const char *hash_name, const unsigned char *msg, size_t msg_len, const unsigned char *param, size_t param_len, unsigned char *emsg, size_t emsg_len) { unsigned char *db; unsigned char seed[SSH_MAX_HASH_DIGEST_LENGTH]; size_t db_len, i, digest_len; SshHash hash; SshCryptoStatus status; if ((status = ssh_hash_allocate(hash_name, &hash)) != SSH_CRYPTO_OK) return status; digest_len = ssh_hash_digest_length(hash_name); /* Check that the size constraints are satisfied. */ if (msg_len > emsg_len - 2 * digest_len - 1) { ssh_hash_free(hash); return SSH_CRYPTO_OPERATION_FAILED; } /* This is: emLen - ||M|| - 2hLen - 1 + hLen + 1 + ||M|| = emLen - hLen. */ db_len = emsg_len - digest_len; if ((db = ssh_calloc(1, db_len)) == NULL) { ssh_hash_free(hash); return SSH_CRYPTO_NO_MEMORY; } ssh_hash_update(hash, param, param_len); if ((status = ssh_hash_final(hash, db)) != SSH_CRYPTO_OK) { ssh_hash_free(hash); return status; } /* Add the "01" before the last msg_len bytes. */ db[db_len - msg_len - 1] = 0x1; /* Now throw in the msg. */ memcpy(db + db_len - msg_len, msg, msg_len); /* Generate a random octet string. */ for (i = 0; i < digest_len; i++) seed[i] = ssh_random_get_byte(); /* Now use the MGF1. */ if ((status = ssh_rsa_mgf1(hash_name, seed, digest_len, emsg + digest_len, db_len)) != SSH_CRYPTO_OK) { ssh_hash_free(hash); ssh_free(db); return status; } /* Xor. */ for (i = 0; i < db_len; i++) emsg[digest_len + i] ^= db[i]; memset(db, 0, db_len); /* Use MGF1 again. */ if ((status = ssh_rsa_mgf1(hash_name, emsg + digest_len, db_len, emsg, digest_len)) != SSH_CRYPTO_OK) { ssh_hash_free(hash); ssh_free(db); return status; } /* Xor the seed. */ for (i = 0; i < digest_len; i++) emsg[i] ^= seed[i]; memset(seed, 0, digest_len); /* Now free the allocated information. */ ssh_hash_free(hash); ssh_free(db); return SSH_CRYPTO_OK; }
/* OAEP decode using MGF1. */ SshCryptoStatus ssh_rsa_oaep_decode_with_mgf1(const char *hash_name, const unsigned char *emsg, size_t emsg_len, const unsigned char *param, size_t param_len, unsigned char **msg, size_t *msg_len) { unsigned char seed[SSH_MAX_HASH_DIGEST_LENGTH]; unsigned char phash[SSH_MAX_HASH_DIGEST_LENGTH]; unsigned char *db = NULL; size_t db_len, i, digest_len; SshHash hash; SshCryptoStatus status; if ((status = ssh_hash_allocate(hash_name, &hash)) != SSH_CRYPTO_OK) return status; digest_len = ssh_hash_digest_length(hash_name); if (emsg_len < 2 * digest_len + 1) { status = SSH_CRYPTO_OPERATION_FAILED; goto failed; } /* Allocate enough working buffers. */ db_len = emsg_len - digest_len; if ((db = ssh_malloc(db_len)) == NULL) { status = SSH_CRYPTO_NO_MEMORY; goto failed; } /* Use the mgf. */ if ((status = ssh_rsa_mgf1(hash_name, emsg + digest_len, db_len, seed, digest_len)) != SSH_CRYPTO_OK) { goto failed; } /* Now xor. */ for (i = 0; i < digest_len; i++) seed[i] ^= emsg[i]; /* Use the mgf again. */ if ((status = ssh_rsa_mgf1(hash_name, seed, digest_len, db, db_len)) != SSH_CRYPTO_OK) { goto failed; } /* Now xor again. */ for (i = 0; i < db_len; i++) db[i] ^= emsg[digest_len + i]; ssh_hash_update(hash, param, param_len); if ((status = ssh_hash_final(hash, phash)) != SSH_CRYPTO_OK) { goto failed; } /* Do the check. */ if (memcmp(db, phash, digest_len) != 0) { status = SSH_CRYPTO_OPERATION_FAILED; goto failed; } for (i = digest_len; i < db_len; i++) { if (db[i] != 0) { if (db[i] != 0x1) { status = SSH_CRYPTO_OPERATION_FAILED; goto failed; } break; } } if (i >= db_len) { status = SSH_CRYPTO_OPERATION_FAILED; goto failed; } /* Now we must have db[i] == 0x1. */ *msg_len = db_len - i - 1; if ((*msg = ssh_malloc(*msg_len)) == NULL) { status = SSH_CRYPTO_NO_MEMORY; goto failed; } memcpy(*msg, db + i + 1, *msg_len); status = SSH_CRYPTO_OK; failed: ssh_hash_free(hash); ssh_free(db); return status; }
static void ssh_eap_md5_client_recv_token(SshEapProtocol protocol, SshEap eap, SshBuffer buf) { SshEapMd5State state; SshEapMd5Params params; SshBuffer pkt = NULL; SshUInt8 b; SshHash hash = NULL; SshCryptoStatus status; unsigned long len; unsigned long name_len; unsigned long secret_len; SshUInt8 *secret_ptr; SshEapToken t; SshUInt8 hashbuf[32]; if (ssh_eap_get_token_type_from_buf(buf) != SSH_EAP_TOKEN_SHARED_SECRET) { ssh_eap_discard_token(eap, protocol, buf, ("unexpected token type")); return; } t = (SshEapToken)ssh_buffer_ptr(buf); if (t == NULL) { ssh_eap_discard_token(eap, protocol, buf, ("invalid token")); return; } secret_ptr = ssh_eap_get_token_secret_ptr(t); secret_len = ssh_eap_get_token_secret_len(t); SSH_ASSERT(secret_ptr != NULL || secret_len == 0); state = ssh_eap_protocol_get_state(protocol); params = ssh_eap_protocol_get_params(protocol); status = SSH_CRYPTO_UNSUPPORTED; name_len = 0; if (params != NULL && params->name_buffer != NULL) { name_len = params->name_length; } if (state->challenge_buffer == NULL) { ssh_eap_discard_token(eap, protocol, buf, "EAP MD5 state lacks authenticator challenge"); goto fail_auth; } status = ssh_hash_allocate("md5", &hash); if (status != SSH_CRYPTO_OK) { ssh_eap_discard_token(eap, protocol, buf, "failed to initialize MD5 function"); goto fail_auth; } len = ssh_hash_digest_length(ssh_hash_name(hash)); if (len > 32) { ssh_eap_fatal(eap, protocol, "MD5 output of unexpected size"); goto fail_auth; } pkt = ssh_eap_create_reply(eap, (SshUInt16)(1 + len + name_len), protocol->impl->id); if (pkt == NULL) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not allocate reply packet."); goto fail_auth; } b = (SshUInt8)(len & 0xFF); if (ssh_buffer_append(pkt,&b,1) != SSH_BUFFER_OK) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not build reply packet."); goto fail_auth; } ssh_hash_reset(hash); ssh_hash_update(hash, &state->response_id, 1); ssh_hash_update(hash, secret_ptr, secret_len); ssh_hash_update(hash, state->challenge_buffer, state->challenge_length); ssh_hash_final(hash, hashbuf); if (ssh_buffer_append(pkt, hashbuf, len) != SSH_BUFFER_OK) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not build reply packet."); goto fail_auth; } if (name_len > 0) { if (ssh_buffer_append(pkt, params->name_buffer, name_len) != SSH_BUFFER_OK) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not build reply packet."); goto fail_auth; } } ssh_eap_protocol_send_response(protocol, eap, pkt); pkt = NULL; ssh_eap_protocol_auth_ok(protocol, eap, SSH_EAP_SIGNAL_NONE, NULL); fail_auth: if (pkt != NULL) ssh_buffer_free(pkt); if (hash != NULL) ssh_hash_free(hash); ssh_eap_md5_reset(protocol,eap); }
strbuf *ssh_rsakex_encrypt(RSAKey *rsa, const ssh_hashalg *h, ptrlen in) { mp_int *b1, *b2; int k, i; char *p; const int HLEN = h->hlen; /* * Here we encrypt using RSAES-OAEP. Essentially this means: * * - we have a SHA-based `mask generation function' which * creates a pseudo-random stream of mask data * deterministically from an input chunk of data. * * - we have a random chunk of data called a seed. * * - we use the seed to generate a mask which we XOR with our * plaintext. * * - then we use _the masked plaintext_ to generate a mask * which we XOR with the seed. * * - then we concatenate the masked seed and the masked * plaintext, and RSA-encrypt that lot. * * The result is that the data input to the encryption function * is random-looking and (hopefully) contains no exploitable * structure such as PKCS1-v1_5 does. * * For a precise specification, see RFC 3447, section 7.1.1. * Some of the variable names below are derived from that, so * it'd probably help to read it anyway. */ /* k denotes the length in octets of the RSA modulus. */ k = (7 + mp_get_nbits(rsa->modulus)) / 8; /* The length of the input data must be at most k - 2hLen - 2. */ assert(in.len > 0 && in.len <= k - 2*HLEN - 2); /* The length of the output data wants to be precisely k. */ strbuf *toret = strbuf_new_nm(); int outlen = k; unsigned char *out = strbuf_append(toret, outlen); /* * Now perform EME-OAEP encoding. First set up all the unmasked * output data. */ /* Leading byte zero. */ out[0] = 0; /* At position 1, the seed: HLEN bytes of random data. */ random_read(out + 1, HLEN); /* At position 1+HLEN, the data block DB, consisting of: */ /* The hash of the label (we only support an empty label here) */ { ssh_hash *s = ssh_hash_new(h); ssh_hash_final(s, out + HLEN + 1); } /* A bunch of zero octets */ memset(out + 2*HLEN + 1, 0, outlen - (2*HLEN + 1)); /* A single 1 octet, followed by the input message data. */ out[outlen - in.len - 1] = 1; memcpy(out + outlen - in.len, in.ptr, in.len); /* * Now use the seed data to mask the block DB. */ oaep_mask(h, out+1, HLEN, out+HLEN+1, outlen-HLEN-1); /* * And now use the masked DB to mask the seed itself. */ oaep_mask(h, out+HLEN+1, outlen-HLEN-1, out+1, HLEN); /* * Now `out' contains precisely the data we want to * RSA-encrypt. */ b1 = mp_from_bytes_be(make_ptrlen(out, outlen)); b2 = mp_modpow(b1, rsa->exponent, rsa->modulus); p = (char *)out; for (i = outlen; i--;) { *p++ = mp_get_byte(b2, i); } mp_free(b1); mp_free(b2); /* * And we're done. */ return toret; }
SshCMStatus ssh_cm_add_crl_with_bindings(SshCMCrl crl, SshCertDBKey *bindings) { SshCertDBEntry *entry; SshCMContext cm = crl->cm; SSH_DEBUG(5, ("CRL add to local database/memory cache.")); if (crl == NULL || cm->db == NULL) { ssh_certdb_key_free(bindings); return SSH_CM_STATUS_FAILURE; } if (cm->config->local_db_writable == FALSE) { ssh_certdb_key_free(bindings); return SSH_CM_STATUS_FAILURE; } /* Allocate a new entry. */ if (ssh_certdb_alloc_entry(cm->db, SSH_CM_DATA_TYPE_CRL, crl, &entry) != SSH_CDBET_OK) { ssh_certdb_key_free(bindings); return SSH_CM_STATUS_COULD_NOT_ALLOCATE; } SSH_DEBUG(SSH_D_MIDOK, ("Explicit crl: %@", ssh_cm_render_crl, crl->crl)); /* Check for collision in the database. Be a optimist anyway... */ if (ssh_cm_crl_check_db_collision(cm, crl, &entry->names)) { unsigned char digest[SSH_MAX_HASH_DIGEST_LENGTH]; size_t length; SshHash hash; SshCertDBEntryList *found; SshCertDBEntryListNode list; SshCMCrl old_crl; /* First fetch colliding old CRL from local cache, timestamp it and clean possible SSH_CM_CRL_FLAG_SKIP-flag */ if (ssh_hash_allocate(SSH_CM_HASH_ALGORITHM, &hash) != SSH_CRYPTO_OK) { SSH_DEBUG(SSH_D_ERROR, ("Can't allocate %s", SSH_CM_HASH_ALGORITHM)); ssh_certdb_release_entry(cm->db, entry); ssh_certdb_key_free(bindings); return SSH_CM_STATUS_COULD_NOT_ALLOCATE; } ssh_hash_update(hash, crl->ber, crl->ber_length); ssh_hash_final(hash, digest); length = ssh_hash_digest_length(ssh_hash_name(hash)); ssh_hash_free(hash); if (length > 8) length = 8; /* Get old CRL from the database. */ if ((ssh_certdb_find(cm->db, SSH_CM_DATA_TYPE_CRL, SSH_CM_KEY_TYPE_BER_HASH, digest, length, &found) == SSH_CDBET_OK) && found->head) { list = found->head; old_crl = list->entry->context; ssh_ber_time_set_from_unix_time(&old_crl->fetch_time, (*cm->config->time_func) (cm->config->time_context)); old_crl->status_flags &= ~SSH_CM_CRL_FLAG_SKIP; SSH_DEBUG(SSH_D_MIDOK, ("CRL exists already in the database, " "updated CRL fetch-time.")); } else { SSH_DEBUG(SSH_D_FAIL, ("CRL exists already in the database, " "could not update CRL fetch-time.")); } ssh_certdb_entry_list_free_all(cm->db, found); /* Prevent database from freeing the CRL */ entry->context = NULL; /* Free the entry allocated. */ ssh_certdb_release_entry(cm->db, entry); ssh_certdb_key_free(bindings); return SSH_CM_STATUS_ALREADY_EXISTS; } /* Initialize the entry. */ crl->entry = entry; if (!ssh_cm_key_set_from_crl(&entry->names, crl)) { /* Prevent database from freeing the CRL */ entry->context = NULL; ssh_certdb_release_entry(cm->db, entry); ssh_certdb_key_free(bindings); return SSH_CM_STATUS_COULD_NOT_ALLOCATE; } if (bindings) ssh_certdb_entry_add_keys(cm->db, entry, bindings); /* Add to the database. */ if (ssh_certdb_add(cm->db, entry) != SSH_CDBET_OK) { /* Prevent database from freeing the CRL */ entry->context = NULL; ssh_certdb_release_entry(cm->db, entry); SSH_DEBUG(4, ("Local database/memory cache denies the addition.")); return SSH_CM_STATUS_COULD_NOT_ALLOCATE; } /* Record CRL addition time */ ssh_ber_time_set_from_unix_time(&crl->fetch_time, (*cm->config->time_func) (cm->config->time_context)); ssh_certdb_release_entry(cm->db, entry); return SSH_CM_STATUS_OK; }
/* There must be room for 36 bytes in `buf'. */ static Boolean generic_ssl_digest(unsigned char *secret, int secret_len, unsigned char *handshake_messages, int handshake_messages_len, Boolean is_client, unsigned char *buf, Boolean include_sender_token) { SshHash md5, sha1; int i; const unsigned char client_label[4] = { 0x43, 0x4c, 0x4e, 0x54 }; const unsigned char sender_label[4] = { 0x53, 0x52, 0x56, 0x52 }; unsigned char pad_36[48], pad_5c[48]; for (i = 0; i < 48; i++) { pad_36[i] = 0x36; pad_5c[i] = 0x5c; } SSH_ASSERT(secret_len == 48); if (ssh_hash_allocate("md5", &md5) != SSH_CRYPTO_OK) return FALSE; if (ssh_hash_allocate("sha1", &sha1) != SSH_CRYPTO_OK) return FALSE; ssh_hash_reset(md5); ssh_hash_update(md5, handshake_messages, handshake_messages_len); if (include_sender_token) ssh_hash_update(md5, is_client ? client_label : sender_label, 4); ssh_hash_update(md5, secret, secret_len); ssh_hash_update(md5, pad_36, 48); if (ssh_hash_final(md5, buf) != SSH_CRYPTO_OK) return FALSE; ssh_hash_reset(md5); ssh_hash_update(md5, secret, secret_len); ssh_hash_update(md5, pad_5c, 48); ssh_hash_update(md5, buf, 16); if (ssh_hash_final(md5, buf) != SSH_CRYPTO_OK) return FALSE; ssh_hash_reset(sha1); ssh_hash_update(sha1, handshake_messages, handshake_messages_len); if (include_sender_token) ssh_hash_update(sha1, is_client ? client_label : sender_label, 4); ssh_hash_update(sha1, secret, secret_len); ssh_hash_update(sha1, pad_36, 40); if (ssh_hash_final(sha1, buf + 16) != SSH_CRYPTO_OK) return FALSE; ssh_hash_reset(sha1); ssh_hash_update(sha1, secret, secret_len); ssh_hash_update(sha1, pad_5c, 40); ssh_hash_update(sha1, buf + 16, 20); if (ssh_hash_final(sha1, buf + 16) != SSH_CRYPTO_OK) return FALSE; ssh_hash_free(md5); ssh_hash_free(sha1); return TRUE; }
mp_int *ssh_rsakex_decrypt( RSAKey *rsa, const ssh_hashalg *h, ptrlen ciphertext) { mp_int *b1, *b2; int outlen, i; unsigned char *out; unsigned char labelhash[64]; ssh_hash *hash; BinarySource src[1]; const int HLEN = h->hlen; /* * Decryption side of the RSA key exchange operation. */ /* The length of the encrypted data should be exactly the length * in octets of the RSA modulus.. */ outlen = (7 + mp_get_nbits(rsa->modulus)) / 8; if (ciphertext.len != outlen) return NULL; /* Do the RSA decryption, and extract the result into a byte array. */ b1 = mp_from_bytes_be(ciphertext); b2 = rsa_privkey_op(b1, rsa); out = snewn(outlen, unsigned char); for (i = 0; i < outlen; i++) out[i] = mp_get_byte(b2, outlen-1-i); mp_free(b1); mp_free(b2); /* Do the OAEP masking operations, in the reverse order from encryption */ oaep_mask(h, out+HLEN+1, outlen-HLEN-1, out+1, HLEN); oaep_mask(h, out+1, HLEN, out+HLEN+1, outlen-HLEN-1); /* Check the leading byte is zero. */ if (out[0] != 0) { sfree(out); return NULL; } /* Check the label hash at position 1+HLEN */ assert(HLEN <= lenof(labelhash)); hash = ssh_hash_new(h); ssh_hash_final(hash, labelhash); if (memcmp(out + HLEN + 1, labelhash, HLEN)) { sfree(out); return NULL; } /* Expect zero bytes followed by a 1 byte */ for (i = 1 + 2 * HLEN; i < outlen; i++) { if (out[i] == 1) { i++; /* skip over the 1 byte */ break; } else if (out[i] != 1) { sfree(out); return NULL; } } /* And what's left is the input message data, which should be * encoded as an ordinary SSH-2 mpint. */ BinarySource_BARE_INIT(src, out + i, outlen - i); b1 = get_mp_ssh2(src); sfree(out); if (get_err(src) || get_avail(src) != 0) { mp_free(b1); return NULL; } /* Success! */ return b1; }