Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
/**
 *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);
}
Ejemplo n.º 3
0
/**
 *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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 6
0
/**
 *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);
}
Ejemplo n.º 7
0
/**
 *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);
}
Ejemplo n.º 8
0
Archivo: pki.c Proyecto: rofl0r/libssh
/*
 * 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;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
/**
 *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);
}
Ejemplo n.º 11
0
Archivo: keys.c Proyecto: rofl0r/libssh
/* 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;
}
Ejemplo n.º 12
0
Archivo: keys.c Proyecto: rofl0r/libssh
/* 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;
}
Ejemplo n.º 14
0
/*
 * 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;
}