/* this function signs the session id */ STRING *ssh_sign_session_id(SSH_SESSION *session, PRIVATE_KEY *privatekey){ SHACTX ctx; unsigned char hash[SHA_DIGEST_LEN+1]; SIGNATURE *sign; STRING *signature; CRYPTO *crypto=session->current_crypto?session->current_crypto:session->next_crypto; #ifdef HAVE_LIBGCRYPT gcry_sexp_t data_sexp; #endif ctx=sha1_init(); sha1_update(ctx,crypto->session_id,SHA_DIGEST_LEN); sha1_final(hash+1,ctx); hash[0]=0; #ifdef DEBUG_CRYPTO ssh_print_hexa("Hash being signed with dsa",hash+1,SHA_DIGEST_LEN); #endif sign=malloc(sizeof(SIGNATURE)); switch(privatekey->type){ case TYPE_DSS: #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&data_sexp,NULL,"%b",SHA_DIGEST_LEN+1,hash); gcry_pk_sign(&sign->dsa_sign,data_sexp,privatekey->dsa_priv); #elif defined HAVE_LIBCRYPTO sign->dsa_sign=DSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->dsa_priv); #ifdef DEBUG_CRYPTO ssh_print_bignum("r",sign->dsa_sign->r); ssh_print_bignum("s",sign->dsa_sign->s); #endif #endif sign->rsa_sign=NULL; break; case TYPE_RSA: #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&data_sexp,NULL,"(data(flags pkcs1)(hash sha1 %b))",SHA_DIGEST_LEN,hash+1); gcry_pk_sign(&sign->rsa_sign,data_sexp,privatekey->rsa_priv); #elif defined HAVE_LIBCRYPTO sign->rsa_sign=RSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->rsa_priv); #endif sign->dsa_sign=NULL; break; } #ifdef HAVE_LIBGCRYPT gcry_sexp_release(data_sexp); #endif sign->type=privatekey->type; if(!sign->dsa_sign && !sign->rsa_sign){ #ifdef HAVE_LIBGCRYPT ssh_set_error(session,SSH_FATAL,"Signing : libgcrypt error"); #elif defined HAVE_LIBCRYPTO ssh_set_error(session,SSH_FATAL,"Signing : openssl error"); #endif signature_free(sign); return NULL; } signature=signature_to_string(sign); signature_free(sign); return signature; }
/** *YGH 40 */ static void signed_wsa_free(signed_wsa* signed_wsa){ int n = signed_wsa->signer.u.certificates.len - 1; if((signed_wsa->signer.type == CERTIFICATE_CHAIN) && ((signed_wsa->signer.u.certificates.buf + n)->version_and_type == 2)){ signature_free(&signed_wsa->signature, (signed_wsa->signer.u.certificates.buf + n)->unsigned_certificate.version_and_type.verification_key.algorithm); }else{ signature_free(&signed_wsa->signature,ECDSA_NISTP256_WITH_SHA256); } signer_identifier_free(&signed_wsa->signer); tobesigned_wsa_free(&signed_wsa->unsigned_wsa); }
/** *YGH 28 */ static void tobe_encrypted_certificate_request_error_free(tobe_encrypted_certificate_request_error* tobe_encrypted_certificate_request_error){ switch(tobe_encrypted_certificate_request_error->signer.u.certificate.version_and_type){ case 2: signature_free(&tobe_encrypted_certificate_request_error->signature, tobe_encrypted_certificate_request_error->signer.u.certificate.unsigned_certificate.version_and_type.verification_key.algorithm); break; case 3: signature_free(&tobe_encrypted_certificate_request_error->signature, tobe_encrypted_certificate_request_error->signer.u.certificate.unsigned_certificate.u.no_root_ca.signature_alg); break; default: break; } signer_identifier_free(&tobe_encrypted_certificate_request_error->signer); }
struct signature_struct *pki_do_sign(ssh_key privatekey, const unsigned char *hash) { struct signature_struct *sign; sign = malloc(sizeof(SIGNATURE)); if (sign == NULL) { return NULL; } sign->type = privatekey->type; switch(privatekey->type) { case SSH_KEYTYPE_DSS: sign->dsa_sign = DSA_do_sign(hash + 1, SHA_DIGEST_LEN, privatekey->dsa); if (sign->dsa_sign == NULL) { signature_free(sign); return NULL; } #ifdef DEBUG_CRYPTO ssh_print_bignum("r", sign->dsa_sign->r); ssh_print_bignum("s", sign->dsa_sign->s); #endif sign->rsa_sign = NULL; break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: sign->rsa_sign = RSA_do_sign(hash + 1, SHA_DIGEST_LEN, privatekey->rsa); if (sign->rsa_sign == NULL) { signature_free(sign); return NULL; } sign->dsa_sign = NULL; break; case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: signature_free(sign); return NULL; } return sign; }
static bool process_hunk(char const *program, struct notify_info *notify, struct memory_block_data const *payload, struct memory_block_signature const *signature) { struct signature_algorithm *sigalg = NULL; struct decompression_algorithm *decompalg = NULL; sigalg = create_sigalg(signature); if (!sigalg) goto err; decompalg = create_decompress(payload); if (!decompalg && payload->compression != STREAM_COMPRESS_NONE) goto err; if (!send_stream(program, notify, payload, sigalg, decompalg)) goto err; if (!signature_update(sigalg, payload->mem.stream->extra_salt, payload->mem.stream->extra_salt_len) || !signature_update(sigalg, signature->shdr->salt, sizeof signature->shdr->salt) || !signature_update(sigalg, signature->hhdr, sizeof *signature->hhdr)) goto err; if (signature->mem.len && !verify_signature(signature, sigalg)) goto err; if (!finish_stream(program, payload, sigalg)) goto err; signature_free(sigalg); return true; err: decompression_free(decompalg); signature_free(sigalg); return false; }
/** *YGH 24 */ void certificate_free(certificate* certificate){ switch(certificate->version_and_type){ case 2: switch(certificate->unsigned_certificate.holder_type){ case ROOT_CA: signature_free(&certificate->u.signature,certificate->unsigned_certificate.version_and_type.verification_key.algorithm); break; default: signature_free(&certificate->u.signature,certificate->unsigned_certificate.u.no_root_ca.signature_alg); } break; case 3: elliptic_curve_point_free(&certificate->u.reconstruction_value); break; default: if(NULL!=certificate->u.signature_material.buf) ARRAY_FREE(&certificate->u.signature_material); } tobesigned_certificate_free(&certificate->unsigned_certificate,certificate->version_and_type); }
/** *YGH 31 */ void certificate_request_free(certificate_request* certificate_request){ switch(certificate_request->signer.type){ case SELF: signature_free(&certificate_request->signature, certificate_request->unsigned_csr.verification_key.algorithm); break; case CERTIFICATE: if(certificate_request->signer.u.certificate.version_and_type == 2) signature_free(&certificate_request->signature, certificate_request->signer.u.certificate.unsigned_certificate.version_and_type.verification_key.algorithm); else if(certificate_request->signer.u.certificate.version_and_type == 3) signature_free(&certificate_request->signature, certificate_request->signer.u.certificate.unsigned_certificate.u.no_root_ca.signature_alg); break; default: break; } signer_identifier_free(&certificate_request->signer); tobesigned_certificate_request_free(&certificate_request->unsigned_csr); }
/* * This function signs the session id (known as H) as a string then * the content of sigbuf */ ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf, ssh_key privatekey) { struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto : session->next_crypto; unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; ssh_string session_str = NULL; ssh_string signature = NULL; struct signature_struct *sign = NULL; SHACTX ctx = NULL; if (privatekey == NULL || !ssh_key_is_private(privatekey)) { return NULL; } session_str = ssh_string_new(SHA_DIGEST_LEN); if (session_str == NULL) { return NULL; } ssh_string_fill(session_str, crypto->session_id, SHA_DIGEST_LEN); ctx = sha1_init(); if (ctx == NULL) { ssh_string_free(session_str); return NULL; } sha1_update(ctx, session_str, ssh_string_len(session_str) + 4); ssh_string_free(session_str); sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf)); sha1_final(hash + 1,ctx); hash[0] = 0; #ifdef DEBUG_CRYPTO ssh_print_hexa("Hash being signed with dsa", hash + 1, SHA_DIGEST_LEN); #endif sign = pki_do_sign(privatekey, hash); if (sign == NULL) { return NULL; } signature = signature_to_string(sign); signature_free(sign); return signature; }
int signature_verify(ssh_session session, ssh_string signature) { ssh_public_key pubkey = NULL; SIGNATURE *sign = NULL; int err; enter_function(); pubkey = publickey_from_string(session,session->next_crypto->server_pubkey); if(pubkey == NULL) { leave_function(); return -1; } if (session->wanted_methods[SSH_HOSTKEYS]) { if(!match(session->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) { ssh_set_error(session, SSH_FATAL, "Public key from server (%s) doesn't match user preference (%s)", pubkey->type_c, session->wanted_methods[SSH_HOSTKEYS]); publickey_free(pubkey); leave_function(); return -1; } } sign = signature_from_string(session, signature, pubkey, pubkey->type); if (sign == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid signature blob"); publickey_free(pubkey); leave_function(); return -1; } ssh_log(session, SSH_LOG_FUNCTIONS, "Going to verify a %s type signature", pubkey->type_c); err = sig_verify(session,pubkey,sign, session->next_crypto->session_id,SHA_DIGEST_LEN); signature_free(sign); session->next_crypto->server_pubkey_type = pubkey->type_c; publickey_free(pubkey); leave_function(); return err; }
/** *YGH 33 */ void signed_data_free(signed_data* signed_data, content_type type){ int n = signed_data->signer.u.certificates.len - 1; switch(signed_data->signer.type){ case CERTIFICATE_DIGEST_WITH_ECDSAP224: signature_free(&signed_data->signature,ECDSA_NISTP224_WITH_SHA224); break; case CERTIFICATE_DIGEST_WITH_ECDSAP256: signature_free(&signed_data->signature,ECDSA_NISTP256_WITH_SHA256); break; case CERTIFICATE_DIGETS_WITH_OTHER_ALGORITHM: signature_free(&signed_data->signature,signed_data->signer.u.other_algorithm.algorithm); break; case CERTIFICATE: if(signed_data->signer.u.certificate.version_and_type == 2) signature_free(&signed_data->signature, signed_data->signer.u.certificate.unsigned_certificate.version_and_type.verification_key.algorithm); else if(signed_data->signer.u.certificate.version_and_type == 3) signature_free(&signed_data->signature, signed_data->signer.u.certificate.unsigned_certificate.u.no_root_ca.signature_alg); break; case CERTIFICATE_CHAIN: if((signed_data->signer.u.certificates.buf + n)->version_and_type == 2) signature_free(&signed_data->signature, (signed_data->signer.u.certificates.buf + n)->unsigned_certificate.version_and_type.verification_key.algorithm); else if((signed_data->signer.u.certificates.buf + n)->version_and_type == 3) signature_free(&signed_data->signature, (signed_data->signer.u.certificates.buf + n)->unsigned_certificate.u.no_root_ca.signature_alg); break; default: break; } signer_identifier_free(&signed_data->signer); tobesigned_data_free(&signed_data->unsigned_data,type); }
/* TODO : split this function in two so it becomes smaller */ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature, ssh_public_key pubkey, int needed_type) { SIGNATURE *sign = NULL; ssh_buffer tmpbuf = NULL; ssh_string rs = NULL; ssh_string type_s = NULL; ssh_string e = NULL; char *type_c = NULL; int type; int len; int rsalen; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sig; #elif defined HAVE_LIBCRYPTO DSA_SIG *sig = NULL; ssh_string r = NULL; ssh_string s = NULL; #endif sign = malloc(sizeof(SIGNATURE)); if (sign == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return NULL; } ZERO_STRUCTP(sign); tmpbuf = ssh_buffer_new(); if (tmpbuf == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); signature_free(sign); return NULL; } if (buffer_add_data(tmpbuf, ssh_string_data(signature), ssh_string_len(signature)) < 0) { signature_free(sign); ssh_buffer_free(tmpbuf); return NULL; } type_s = buffer_get_ssh_string(tmpbuf); if (type_s == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid signature packet"); signature_free(sign); ssh_buffer_free(tmpbuf); return NULL; } type_c = ssh_string_to_char(type_s); ssh_string_free(type_s); if (type_c == NULL) { signature_free(sign); ssh_buffer_free(tmpbuf); return NULL; } type = ssh_type_from_name(type_c); SAFE_FREE(type_c); if (needed_type != type) { ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s", ssh_type_to_char(type)); signature_free(sign); ssh_buffer_free(tmpbuf); return NULL; } switch(needed_type) { case SSH_KEYTYPE_DSS: rs = buffer_get_ssh_string(tmpbuf); ssh_buffer_free(tmpbuf); /* 40 is the dual signature blob len. */ if (rs == NULL || ssh_string_len(rs) != 40) { ssh_string_free(rs); signature_free(sign); return NULL; } /* we make use of strings (because we have all-made functions to convert * them to bignums (ou pas ;) */ #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))", 20 ,ssh_string_data(rs), 20,(unsigned char *)ssh_string_data(rs) + 20)) { ssh_string_free(rs); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO r = ssh_string_new(20); s = ssh_string_new(20); if (r == NULL || s == NULL) { ssh_string_free(r); ssh_string_free(s); ssh_string_free(rs); signature_free(sign); return NULL; } ssh_string_fill(r, ssh_string_data(rs), 20); ssh_string_fill(s, (char *)ssh_string_data(rs) + 20, 20); sig = DSA_SIG_new(); if (sig == NULL) { ssh_string_free(r); ssh_string_free(s); ssh_string_free(rs); signature_free(sign); return NULL; } sig->r = make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */ sig->s = make_string_bn(s); ssh_string_free(r); ssh_string_free(s); if (sig->r == NULL || sig->s == NULL) { ssh_string_free(rs); DSA_SIG_free(sig); signature_free(sign); return NULL; } #endif #ifdef DEBUG_CRYPTO ssh_print_hexa("r", ssh_string_data(rs), 20); ssh_print_hexa("s", (const unsigned char *)ssh_string_data(rs) + 20, 20); #endif ssh_string_free(rs); sign->type = SSH_KEYTYPE_DSS; sign->dsa_sign = sig; return sign; case SSH_KEYTYPE_RSA: e = buffer_get_ssh_string(tmpbuf); ssh_buffer_free(tmpbuf); if (e == NULL) { signature_free(sign); return NULL; } len = ssh_string_len(e); #ifdef HAVE_LIBGCRYPT rsalen = (gcry_pk_get_nbits(pubkey->rsa_pub) + 7) / 8; #elif defined HAVE_LIBCRYPTO rsalen = RSA_size(pubkey->rsa_pub); #endif if (len > rsalen) { ssh_string_free(e); signature_free(sign); ssh_set_error(session, SSH_FATAL, "Signature too big! %d instead of %d", len, rsalen); return NULL; } if (len < rsalen) { ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d", len, rsalen); } sign->type = SSH_KEYTYPE_RSA; #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))", ssh_string_len(e), ssh_string_data(e))) { signature_free(sign); ssh_string_free(e); return NULL; } sign->rsa_sign = sig; #elif defined HAVE_LIBCRYPTO sign->rsa_sign = e; #endif #ifdef DEBUG_CRYPTO ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len); ssh_print_hexa("RSA signature", ssh_string_data(e), len); #endif #ifdef HAVE_LIBGCRYPT ssh_string_free(e); #endif return sign; default: return NULL; } return NULL; }
/* this function signs the session id */ ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey) { struct ssh_crypto_struct *crypto=session->current_crypto ? session->current_crypto : session->next_crypto; unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; ssh_string signature = NULL; SIGNATURE *sign = NULL; SHACTX ctx = NULL; #ifdef HAVE_LIBGCRYPT gcry_sexp_t data_sexp; #endif ctx = sha1_init(); if (ctx == NULL) { return NULL; } sha1_update(ctx,crypto->session_id,SHA_DIGEST_LEN); sha1_final(hash + 1,ctx); hash[0] = 0; #ifdef DEBUG_CRYPTO ssh_print_hexa("Hash being signed with dsa",hash+1,SHA_DIGEST_LEN); #endif sign = malloc(sizeof(SIGNATURE)); if (sign == NULL) { return NULL; } ZERO_STRUCTP(sign); switch(privatekey->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&data_sexp, NULL, "%b", SHA_DIGEST_LEN + 1, hash) || gcry_pk_sign(&sign->dsa_sign, data_sexp, privatekey->dsa_priv)) { ssh_set_error(session, SSH_FATAL, "Signing: libgcrypt error"); gcry_sexp_release(data_sexp); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO sign->dsa_sign = DSA_do_sign(hash + 1, SHA_DIGEST_LEN, privatekey->dsa_priv); if (sign->dsa_sign == NULL) { ssh_set_error(session, SSH_FATAL, "Signing: openssl error"); signature_free(sign); return NULL; } #ifdef DEBUG_CRYPTO ssh_print_bignum("r",sign->dsa_sign->r); ssh_print_bignum("s",sign->dsa_sign->s); #endif #endif /* HAVE_LIBCRYPTO */ sign->rsa_sign = NULL; break; case SSH_KEYTYPE_RSA: #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(hash sha1 %b))", SHA_DIGEST_LEN, hash + 1) || gcry_pk_sign(&sign->rsa_sign, data_sexp, privatekey->rsa_priv)) { ssh_set_error(session, SSH_FATAL, "Signing: libgcrypt error"); gcry_sexp_release(data_sexp); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO sign->rsa_sign = RSA_do_sign(hash + 1, SHA_DIGEST_LEN, privatekey->rsa_priv); if (sign->rsa_sign == NULL) { ssh_set_error(session, SSH_FATAL, "Signing: openssl error"); signature_free(sign); return NULL; } #endif sign->dsa_sign = NULL; break; default: signature_free(sign); return NULL; } #ifdef HAVE_LIBGCRYPT gcry_sexp_release(data_sexp); #endif sign->type = privatekey->type; signature = signature_to_string(sign); signature_free(sign); return signature; }
static struct decompression_algorithm * create_decompress(struct memory_block_data const *payload) { struct decompression_algorithm *alg = NULL; struct iovec decomp_vec = { .iov_base = g_decompress_buffer, .iov_len = sizeof g_decompress_buffer, }; switch (payload->compression) { case STREAM_COMPRESS_NONE: if (payload->len != payload->mem.len) { fprintf(stderr, "compression len mismatch (%zu vs. %zu)\n", payload->len, payload->mem.len); return false; } return NULL; case STREAM_COMPRESS_GZIP: alg = decompression_algorithm_gzip_create(&decomp_vec); break; case STREAM_COMPRESS_XZ: alg = decompression_algorithm_xz_create(&decomp_vec); break; default: fprintf(stderr, "unknown compression mode %u\n", payload->compression); return false; } if (!alg) { fprintf(stderr, "failed to create decompression algorithm %d\n", payload->compression); return false; } return alg; } static struct signature_algorithm * create_sigalg(struct memory_block_signature const *signature) { struct signature_algorithm *sigalg = NULL; if ((signature->type != STREAM_SIGNATURE_NONE && signature->mem.len != ~0u) || (signature->type == STREAM_SIGNATURE_NONE && signature->mem.len == ~0u)) { fprintf(stderr, "bad signature length %zu\n", signature->mem.len); return false; } switch (signature->type) { case STREAM_SIGNATURE_NONE: sigalg = signature_algorithm_none_create(); break; case STREAM_SIGNATURE_MD5: sigalg = signature_algorithm_md5_create(); break; case STREAM_SIGNATURE_SHA1: sigalg = signature_algorithm_sha1_create(); break; case STREAM_SIGNATURE_SHA256: sigalg = signature_algorithm_sha256_create(); break; case STREAM_SIGNATURE_SHA512: sigalg = signature_algorithm_sha512_create(); break; case STREAM_SIGNATURE_X509: sigalg = signature_algorithm_x509_create(); break; case STREAM_SIGNATURE_GPG: /* \todo: implement me */ fprintf(stderr, "signature type %u not implemented yet\n", signature->type); return false; default: fprintf(stderr, "unknown signature type %u\n", signature->type); return false; } if (!sigalg) { fprintf(stderr, "failed to create signature algorithm %d\n", signature->type); return false; } if (!set_signature_opts(sigalg, signature->opts)) goto err; if (signature->pre.len) { unsigned char sig[MAX_SIGNATURE_SIZE]; if (signature->pre.len > sizeof sig) { fprintf(stderr, "signature prefix too large (%zu)\n", signature->pre.len); goto err; } if (!stream_data_read(signature->pre.stream, &sig, signature->pre.len, false)) { fprintf(stderr, "failed to read signature\n"); goto err; } switch (signature_setopt(sigalg, "info-bin", sig, signature->pre.len)) { case SIGNATURE_SETOPT_SUCCESS: break; case SIGNATURE_SETOPT_NOOPT: fprintf(stderr, "signature prefix not supported\n"); goto err; case SIGNATURE_SETOPT_ERROR: fprintf(stderr, "failed to register signature prefix\n"); goto err; } } if (!signature_reset(sigalg)) goto err; return sigalg; err: signature_free(sigalg); return NULL; } static bool finish_stream(char const *program, struct memory_block_data const *payload, struct signature_algorithm *sigalg) { pid_t pid = -1; int status; pid = fork(); if (pid < 0) { perror("fork()"); goto err; } if (pid == 0) { int fd_null; char size_str[sizeof(size_t)*3 + 2]; char type_str[sizeof(unsigned int)*3 + 2]; if (!signature_setenv(sigalg)) { fprintf(stderr, "failed to export signature details\n"); _exit(1); } close(0); fd_null = open("/dev/null", O_RDONLY|O_NOCTTY); if (fd_null < 0) { perror("open(/dev/null)"); goto err_child; } else if (fd_null != 0) { fprintf(stderr, "failed to redirect stdin\n"); close(fd_null); goto err_child; } sprintf(size_str, "%zu", payload->len); sprintf(type_str, "%u", payload->type); execlp(program, program, "finish", type_str, size_str, NULL); perror("execlp()"); err_child: _exit(1); } if (TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)) < 0) { perror("waitpid()"); goto err; } pid = -1; if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { fprintf(stderr, "program failed with %d\n", status); goto err; } return true; err: if (pid != -1) { kill(pid, SIGTERM); waitpid(pid, NULL, 0); } return false; }
/* * This function signs the session id (known as H) as a string then * the content of sigbuf */ STRING *ssh_do_sign(SSH_SESSION *session, BUFFER *sigbuf, PRIVATE_KEY *privatekey) { CRYPTO *crypto = session->current_crypto ? session->current_crypto : session->next_crypto; unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; STRING *session_str = NULL; STRING *signature = NULL; SIGNATURE *sign = NULL; SHACTX ctx = NULL; #ifdef HAVE_LIBGCRYPT gcry_sexp_t gcryhash; #endif session_str = string_new(SHA_DIGEST_LEN); if (session_str == NULL) { return NULL; } string_fill(session_str, crypto->session_id, SHA_DIGEST_LEN); ctx = sha1_init(); if (ctx == NULL) { string_free(session_str); return NULL; } sha1_update(ctx, session_str, string_len(session_str) + 4); string_free(session_str); sha1_update(ctx, buffer_get(sigbuf), buffer_get_len(sigbuf)); sha1_final(hash + 1,ctx); hash[0] = 0; #ifdef DEBUG_CRYPTO ssh_print_hexa("Hash being signed with dsa", hash + 1, SHA_DIGEST_LEN); #endif sign = malloc(sizeof(SIGNATURE)); if (sign == NULL) { return NULL; } switch(privatekey->type) { case TYPE_DSS: #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN + 1, hash) || gcry_pk_sign(&sign->dsa_sign, gcryhash, privatekey->dsa_priv)) { ssh_set_error(session, SSH_FATAL, "Signing: libcrypt error"); gcry_sexp_release(gcryhash); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO sign->dsa_sign = DSA_do_sign(hash + 1, SHA_DIGEST_LEN, privatekey->dsa_priv); if (sign->dsa_sign == NULL) { ssh_set_error(session, SSH_FATAL, "Signing: openssl error"); signature_free(sign); return NULL; } #ifdef DEBUG_CRYPTO ssh_print_bignum("r", sign->dsa_sign->r); ssh_print_bignum("s", sign->dsa_sign->s); #endif #endif /* HAVE_LIBCRYPTO */ sign->rsa_sign = NULL; break; case TYPE_RSA: #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&gcryhash, NULL, "(data(flags pkcs1)(hash sha1 %b))", SHA_DIGEST_LEN, hash + 1) || gcry_pk_sign(&sign->rsa_sign, gcryhash, privatekey->rsa_priv)) { ssh_set_error(session, SSH_FATAL, "Signing: libcrypt error"); gcry_sexp_release(gcryhash); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO sign->rsa_sign = RSA_do_sign(hash + 1, SHA_DIGEST_LEN, privatekey->rsa_priv); if (sign->rsa_sign == NULL) { ssh_set_error(session, SSH_FATAL, "Signing: openssl error"); signature_free(sign); return NULL; } #endif sign->dsa_sign = NULL; break; } #ifdef HAVE_LIBGCRYPT gcry_sexp_release(gcryhash); #endif sign->type = privatekey->type; signature = signature_to_string(sign); signature_free(sign); return signature; }