DH * mm_choose_dh(int min, int nbits, int max) { BIGNUM *p, *g; int success = 0; Buffer m; buffer_init(&m); buffer_put_int(&m, min); buffer_put_int(&m, nbits); buffer_put_int(&m, max); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m); debug3("%s: waiting for MONITOR_ANS_MODULI", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m); success = buffer_get_char(&m); if (success == 0) fatal("%s: MONITOR_ANS_MODULI failed", __func__); if ((p = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); if ((g = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); buffer_get_bignum2(&m, p); buffer_get_bignum2(&m, g); debug3("%s: remaining %d", __func__, buffer_len(&m)); buffer_free(&m); return (dh_new_group(g, p)); }
void mm_jpake_step1(struct modp_group *grp, u_char **id, u_int *id_len, BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, u_char **priv1_proof, u_int *priv1_proof_len, u_char **priv2_proof, u_int *priv2_proof_len) { Buffer m; debug3("%s entering", __func__); buffer_init(&m); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_JPAKE_STEP1, &m); debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_JPAKE_STEP1, &m); if ((*priv1 = BN_new()) == NULL || (*priv2 = BN_new()) == NULL || (*g_priv1 = BN_new()) == NULL || (*g_priv2 = BN_new()) == NULL) fatal("%s: BN_new", __func__); *id = buffer_get_string(&m, id_len); /* priv1 and priv2 are, well, private */ buffer_get_bignum2(&m, *g_priv1); buffer_get_bignum2(&m, *g_priv2); *priv1_proof = buffer_get_string(&m, priv1_proof_len); *priv2_proof = buffer_get_string(&m, priv2_proof_len); buffer_free(&m); }
int mm_answer_jpake_step2(int sock, Buffer *m) { struct jpake_ctx *pctx = authctxt->jpake_ctx; u_char *x1_proof, *x2_proof, *x4_s_proof; u_int x1_proof_len, x2_proof_len, x4_s_proof_len; if (pctx == NULL) fatal("%s: pctx == NULL", __func__); if ((pctx->g_x1 = BN_new()) == NULL || (pctx->g_x2 = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(m, pctx->g_x1); buffer_get_bignum2(m, pctx->g_x2); pctx->client_id = buffer_get_string(m, &pctx->client_id_len); x1_proof = buffer_get_string(m, &x1_proof_len); x2_proof = buffer_get_string(m, &x2_proof_len); jpake_step2(pctx->grp, pctx->s, pctx->g_x3, pctx->g_x1, pctx->g_x2, pctx->x4, pctx->client_id, pctx->client_id_len, pctx->server_id, pctx->server_id_len, x1_proof, x1_proof_len, x2_proof, x2_proof_len, &pctx->b, &x4_s_proof, &x4_s_proof_len); JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__)); bzero(x1_proof, x1_proof_len); bzero(x2_proof, x2_proof_len); xfree(x1_proof); xfree(x2_proof); buffer_clear(m); buffer_put_bignum2(m, pctx->b); buffer_put_string(m, x4_s_proof, x4_s_proof_len); debug3("%s: sending step2", __func__); mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m); bzero(x4_s_proof, x4_s_proof_len); xfree(x4_s_proof); monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1); return 0; }
int mm_answer_sesskey(int sock, Buffer *m) { BIGNUM *p; int rsafail; /* Turn off permissions */ monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0); if ((p = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(m, p); rsafail = ssh1_session_key(p); buffer_clear(m); buffer_put_int(m, rsafail); buffer_put_bignum2(m, p); BN_clear_free(p); mm_request_send(sock, MONITOR_ANS_SESSKEY, m); /* Turn on permissions for sessid passing */ monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); return (0); }
BIGNUM * mm_auth_rsa_generate_challenge(Key *key) { Buffer m; BIGNUM *challenge; u_char *blob; u_int blen; debug3("%s entering", __func__); if ((challenge = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); key->type = KEY_RSA; /* XXX cheat for key_to_blob */ if (key_to_blob(key, &blob, &blen) == 0) fatal("%s: key_to_blob failed", __func__); key->type = KEY_RSA1; buffer_init(&m); buffer_put_string(&m, blob, blen); xfree(blob); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m); buffer_get_bignum2(&m, challenge); buffer_free(&m); return (challenge); }
/* * Verify Schnorr signature 'sig' of length 'siglen' against public exponent * g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g' using a * SHA256 hash. * Signature hash will be salted with 'idlen' bytes from 'id'. * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. */ int schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, const BIGNUM *g_x, const u_char *id, u_int idlen, const u_char *sig, u_int siglen) { Buffer b; int ret = -1; u_int rlen; BIGNUM *r, *e; e = r = NULL; if ((e = BN_new()) == NULL || (r = BN_new()) == NULL) { error("%s: BN_new", __func__); goto out; } /* Extract g^v and r from signature blob */ buffer_init(&b); buffer_append(&b, sig, siglen); SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), "%s: sigblob", __func__)); buffer_get_bignum2(&b, e); buffer_get_bignum2(&b, r); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("%s: remaining bytes in signature %d", __func__, rlen); goto out; } ret = schnorr_verify(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256, g_x, id, idlen, r, e); out: BN_clear_free(e); BN_clear_free(r); return ret; }
int mm_answer_rsa_keyallowed(int sock, Buffer *m) { BIGNUM *client_n; Key *key = NULL; u_char *blob = NULL; u_int blen = 0; int allowed = 0; debug3("%s entering", __func__); auth_method = "rsa"; if (options.rsa_authentication && authctxt->valid) { if ((client_n = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(m, client_n); allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); BN_clear_free(client_n); } buffer_clear(m); buffer_put_int(m, allowed); buffer_put_int(m, forced_command != NULL); /* clear temporarily storage (used by generate challenge) */ monitor_reset_key_state(); if (allowed && key != NULL) { key->type = KEY_RSA; /* cheat for key_to_blob */ if (key_to_blob(key, &blob, &blen) == 0) fatal("%s: key_to_blob failed", __func__); buffer_put_string(m, blob, blen); /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = blen; key_blobtype = MM_RSAUSERKEY; } if (key != NULL) key_free(key); mm_append_debug(m); mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); return (0); }
int mm_ssh1_session_key(BIGNUM *num) { int rsafail; Buffer m; buffer_init(&m); buffer_put_bignum2(&m, num); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m); rsafail = buffer_get_int(&m); buffer_get_bignum2(&m, num); buffer_free(&m); return (rsafail); }
void mm_jpake_step2(struct modp_group *grp, BIGNUM *s, BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, const u_char *theirid, u_int theirid_len, const u_char *myid, u_int myid_len, const u_char *theirpub1_proof, u_int theirpub1_proof_len, const u_char *theirpub2_proof, u_int theirpub2_proof_len, BIGNUM **newpub, u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len) { Buffer m; debug3("%s entering", __func__); buffer_init(&m); /* monitor already has all bignums except theirpub1, theirpub2 */ buffer_put_bignum2(&m, theirpub1); buffer_put_bignum2(&m, theirpub2); /* monitor already knows our id */ buffer_put_string(&m, theirid, theirid_len); buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len); buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_JPAKE_STEP2, &m); debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_JPAKE_STEP2, &m); if ((*newpub = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(&m, *newpub); *newpub_exponent_proof = buffer_get_string(&m, newpub_exponent_proof_len); buffer_free(&m); }
int mm_answer_jpake_key_confirm(int sock, Buffer *m) { struct jpake_ctx *pctx = authctxt->jpake_ctx; u_char *x2_s_proof; u_int x2_s_proof_len; if (pctx == NULL) fatal("%s: pctx == NULL", __func__); if ((pctx->a = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(m, pctx->a); x2_s_proof = buffer_get_string(m, &x2_s_proof_len); jpake_key_confirm(pctx->grp, pctx->s, pctx->a, pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2, pctx->server_id, pctx->server_id_len, pctx->client_id, pctx->client_id_len, session_id2, session_id2_len, x2_s_proof, x2_s_proof_len, &pctx->k, &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len); JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__)); bzero(x2_s_proof, x2_s_proof_len); buffer_clear(m); /* pctx->k is sensitive, not sent */ buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); debug3("%s: sending confirmation hash", __func__); mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m); monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1); return 0; }
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; }
// // バッファからキー情報を取り出す(for SSH2) // NOTE: 返値はアロケート領域になるので、呼び出し側で解放すること。 // Key *key_from_blob(char *data, int blen) { int keynamelen, len; char key[128]; RSA *rsa = NULL; DSA *dsa = NULL; EC_KEY *ecdsa = NULL; EC_POINT *q = NULL; char *curve = NULL; Key *hostkey; // hostkey ssh_keytype type; unsigned char *pk = NULL; hostkey = malloc(sizeof(Key)); if (hostkey == NULL) goto error; memset(hostkey, 0, sizeof(Key)); keynamelen = get_uint32_MSBfirst(data); if (keynamelen >= sizeof(key)) { goto error; } data += 4; memcpy(key, data, keynamelen); key[keynamelen] = 0; data += keynamelen; type = get_keytype_from_name(key); switch (type) { case KEY_RSA: // RSA key rsa = RSA_new(); if (rsa == NULL) { goto error; } rsa->n = BN_new(); rsa->e = BN_new(); if (rsa->n == NULL || rsa->e == NULL) { goto error; } buffer_get_bignum2(&data, rsa->e); buffer_get_bignum2(&data, rsa->n); hostkey->type = type; hostkey->rsa = rsa; break; case KEY_DSA: // DSA key dsa = DSA_new(); if (dsa == NULL) { goto error; } dsa->p = BN_new(); dsa->q = BN_new(); dsa->g = BN_new(); dsa->pub_key = BN_new(); if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL || dsa->pub_key == NULL) { goto error; } buffer_get_bignum2(&data, dsa->p); buffer_get_bignum2(&data, dsa->q); buffer_get_bignum2(&data, dsa->g); buffer_get_bignum2(&data, dsa->pub_key); hostkey->type = type; hostkey->dsa = dsa; break; case KEY_ECDSA256: // ECDSA case KEY_ECDSA384: case KEY_ECDSA521: curve = buffer_get_string(&data, NULL); if (type != key_curve_name_to_keytype(curve)) { goto error; } ecdsa = EC_KEY_new_by_curve_name(keytype_to_cipher_nid(type)); if (ecdsa == NULL) { goto error; } q = EC_POINT_new(EC_KEY_get0_group(ecdsa)); if (q == NULL) { goto error; } buffer_get_ecpoint(&data, EC_KEY_get0_group(ecdsa), q); if (key_ec_validate_public(EC_KEY_get0_group(ecdsa), q) == -1) { goto error; } if (EC_KEY_set_public_key(ecdsa, q) != 1) { goto error; } hostkey->type = type; hostkey->ecdsa = ecdsa; break; case KEY_ED25519: pk = buffer_get_string(&data, &len); if (pk == NULL) goto error; if (len != ED25519_PK_SZ) goto error; hostkey->type = type; hostkey->ed25519_pk = pk; pk = NULL; break; default: // unknown key goto error; } return (hostkey); error: if (rsa != NULL) RSA_free(rsa); if (dsa != NULL) DSA_free(dsa); if (ecdsa != NULL) EC_KEY_free(ecdsa); free(hostkey); return NULL; }
int ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { ECDSA_SIG *sig; int hash_alg; u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; u_int len, dlen; int rlen, ret; Buffer b, bb; char *ktype; if (key == NULL || key_type_plain(key->type) != KEY_ECDSA || key->ecdsa == NULL) { error("%s: no ECDSA key", __func__); return -1; } /* fetch signature */ buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_string(&b, NULL); if (strcmp(key_ssh_name_plain(key), ktype) != 0) { error("%s: cannot handle type %s", __func__, ktype); buffer_free(&b); free(ktype); return -1; } free(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("%s: remaining bytes in signature %d", __func__, rlen); free(sigblob); return -1; } /* parse signature */ if ((sig = ECDSA_SIG_new()) == NULL) fatal("%s: ECDSA_SIG_new failed", __func__); buffer_init(&bb); buffer_append(&bb, sigblob, len); buffer_get_bignum2(&bb, sig->r); buffer_get_bignum2(&bb, sig->s); if (buffer_len(&bb) != 0) fatal("%s: remaining bytes in inner sigblob", __func__); buffer_free(&bb); /* clean up */ explicit_bzero(sigblob, len); free(sigblob); /* hash the data */ hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { error("%s: bad hash algorithm %d", __func__, hash_alg); return -1; } if (ssh_digest_memory(hash_alg, data, datalen, digest, sizeof(digest)) != 0) { error("%s: digest_memory failed", __func__); return -1; } ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa); explicit_bzero(digest, sizeof(digest)); ECDSA_SIG_free(sig); debug("%s: signature %s", __func__, ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); return ret; }
int ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { ECDSA_SIG *sig; const EVP_MD *evp_md; EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen; int rlen, ret; Buffer b, bb; char *ktype; if (key == NULL || key->ecdsa == NULL || (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) { error("%s: no ECDSA key", __func__); return -1; } evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid); /* fetch signature */ buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_string(&b, NULL); if (strcmp(key_ssh_name_plain(key), ktype) != 0) { error("%s: cannot handle type %s", __func__, ktype); buffer_free(&b); free(ktype); return -1; } free(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("%s: remaining bytes in signature %d", __func__, rlen); free(sigblob); return -1; } /* parse signature */ if ((sig = ECDSA_SIG_new()) == NULL) fatal("%s: ECDSA_SIG_new failed", __func__); if ((sig->r = BN_new()) == NULL || (sig->s = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); buffer_init(&bb); buffer_append(&bb, sigblob, len); buffer_get_bignum2(&bb, sig->r); buffer_get_bignum2(&bb, sig->s); if (buffer_len(&bb) != 0) fatal("%s: remaining bytes in inner sigblob", __func__); buffer_free(&bb); /* clean up */ memset(sigblob, 0, len); free(sigblob); /* hash the data */ EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa); memset(digest, 'd', sizeof(digest)); ECDSA_SIG_free(sig); debug("%s: signature %s", __func__, ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); return ret; }