Exemplo n.º 1
0
static int test_sign(const char *private_key, const char *public_key, bool success)
{
	char *sig = NULL;
	char *file = NULL;
	int ret = -1;

	sig = str_or_die("%s/sig", test_dir);
	file = __FILE__;

	if (sign(private_key, public_key, file, sig) < 0) {
		goto error;
	}

	if (!signature_init(public_key, NULL)) {
		goto error;
	}

	// Check if signature match
	check_goto(signature_verify(file, sig, false) == success, error);

	// Check signature against wrong file
	check_goto(signature_verify(sig, sig, false) == false, error);

	ret = 0;

error:
	signature_deinit();
	free(sig);
	return ret;
}
int do_sunxi_boot_signature(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	int ret;
	int m_ok = 1;

	ret = signature_verify("boot");
	if(!ret)
	{
		ret = signature_verify("system");
	}
    if(ret)
    {
    	printf("signature verify failed\n");

        __u32 private_start;
        __u32 private_size;
        __u32 erase_block_once=SIG_ERASE_BUFFER_SIZE;
        char  last_back[SIG_SMALL_BUFFER_SIZE];
        char* private_data = NULL;

		private_start = sunxi_partition_get_offset_byname("private");
		private_size  = sunxi_partition_get_size_byname("private") * 512;

		private_data = malloc(SIG_ERASE_BUFFER_SIZE);
		if(!private_data)
		{
			printf("not enough memory for sig erase\n");

			private_data = last_back;
			erase_block_once = SIG_SMALL_BUFFER_SIZE;
			m_ok = 0;
		}
        memset(private_data,0xff,erase_block_once);
        while(private_size>=erase_block_once)
        {
             sunxi_flash_write(private_start,erase_block_once/512,private_data);
             private_start += erase_block_once/512;
             private_size -= erase_block_once;
        }
        if(private_size)
        {
            sunxi_flash_write(private_start,private_size/512,private_data);
        }
        if(m_ok)
        {
        	free(private_data);
    	}
    }

    return 0;

}
static bool	send_stream(char const *program,
			    struct notify_info *notify,
			    struct memory_block_data const *payload,
			    struct signature_algorithm *sigalg,
			    struct decompression_algorithm *decompalg)
{
	struct decompressor		decomp = { .pid = -1 };
	size_t				len;
	pid_t				pid = -1;
	int				pfds[2] = { -1, -1 };
	int				status;

	notification_send(notify, "s", 1);

	if (pipe(pfds) < 0) {
		perror("pipe(<pfds>)");
		goto err;
	}

	pid = fork();
	if (pid < 0) {
		perror("fork()");
		goto err;
	}

	if (pid == 0) {
		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(pfds[1]);
		if (dup2(pfds[0], 0) < 0) {
			perror("dup2()");
			_exit(1);
		}

		if (pfds[0] != 0)
			close(pfds[0]);

		sprintf(size_str, "%zu", payload->len);
		sprintf(type_str, "%u", payload->type);

		execlp(program, program, "stream", type_str, size_str, NULL);
		perror("execlp()");
		_exit(1);
	}

	close(pfds[0]);
	pfds[0] = -1;

	if (!decompressor_run(&decomp, decompalg,
			      payload->mem.stream->fd, payload->mem.len)) {
		fprintf(stderr, "failed to start decompressor\n");
		goto err;
	}

	for (len = 0; len < payload->len && !payload->mem.stream->is_eos;) {
		ssize_t		l;

		/* \todo: implement decompressor */
		l = tee(decomp.fd_out, pfds[1],
			payload->len - len, SPLICE_F_MORE);
		if (l == 0)
			payload->mem.stream->is_eos = true;
		else if (l < 0 && errno == EINTR) {
			continue;
		} else if (l < 0) {
			perror("tee()");
			break;
		}

		notification_handle_read(notify, l);

		if (!signature_pipein(sigalg, decomp.fd_out, l))
			break;

		len += l;
	}
	close(pfds[1]);
	pfds[1] = -1;

	if (!decompressor_wait(&decomp))
		goto err;

	if (len != payload->len) {
		fprintf(stderr, "failed to read all payload data (%zu < %zu)\n",
			len, payload->len);
		goto err;
	}

	notification_send(notify, "w", 1);

	if (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;
	}

	notification_send(notify, "e\0", 2);

	return true;

err:
	if (pfds[0] != -1)
		close(pfds[0]);

	if (pfds[1] != -1)
		close(pfds[0]);

	if (pid != -1) {
		kill(pid, SIGTERM);
		waitpid(pid, NULL, 0);
	}

	decompressor_wait(&decomp);

	notification_send(notify, "e\1", 2);

	return false;
}

static bool	verify_signature(struct memory_block_signature const *signature,
				 struct signature_algorithm	*sigalg)
{
	be32_t		tmp;
	size_t		len;
	unsigned char	sig[MAX_SIGNATURE_SIZE];

	if (!stream_data_read(signature->mem.stream,
			      &tmp, sizeof tmp, false)) {
		fprintf(stderr, "failed to read signature length\n");
		return false;
	}

	len = be32toh(tmp);
	if (len > sizeof sig) {
		fprintf(stderr, "signature too large (%zu)\n", len);
		return false;
	}

	if (!stream_data_read(signature->mem.stream, &sig, len, false)) {
		fprintf(stderr, "failed to read signature\n");
		return false;
	}

	if (!signature_verify(sigalg, sig, len)) {
		fprintf(stderr, "failed to verify signature\n");
		return false;
	}

	return true;
}
Exemplo n.º 4
0
/*Run a benchmark with different curve parameters and print CSV result to out
 *Comma-Separated Values (CSV), RFC 4180: http://tools.ietf.org/html/rfc4180 */
void benchmark(FILE* out, int i)
{
	//Print CSV header
	fprintf(out, "Curve, Public key generation time, Signature generation time, Signature verification time, Operation time\r\n");

	//If the illiterator is invalid use default illiterator
	if(i < 1)
		i = DEFAULT_TEST_ILLITERATOR;	

	//Loop through all curves, since we're benchmarking them towards eachother.
	int curve_i;
	for(curve_i = 0;curve_i < NUMBER_OF_CURVES;curve_i++)
	{
		//Set initial timer
		clock_t start = clock();

		int test_i;

		//Load curve
		domain_parameters curve = domain_parameters_init();
		domain_parameters_load_curve(curve, curve_i);

		//Print curve name
		fprintf(out, "%s, ", curve->name);

		//Get a private key
		mpz_t d;mpz_init(d);
		mpz_sub_ui(d, curve->n, 2);	//Private key must be between 1 and n-1

		//Get a message to sign
		mpz_t m;mpz_init(m);
		mpz_sub_ui(m, curve->n, 2);	//Must be between 1 and n-1
		//NOTE: I assume we're using a hash algorithm giving result with the biggest bit-length possible

		//Initialize a signature
		signature sig = signature_init();

		//Initialize public key
		point Q = point_init();

		//Save time at the start of public key generation
		clock_t start_gen_Q = clock();

		//Generate public key
		for(test_i = 0; test_i < i; test_i++)		
			signature_generate_key(Q, d, curve);

		//Save time between public key generation and signature generation
		clock_t start_sign = clock();

		//Generate signature
		for(test_i = 0; test_i < i; test_i++)
			signature_sign(sig, m, d, curve);

		//Save time between signature generation and signature verification
		clock_t start_verify = clock();

		//Verify signature
		bool result;
		for(test_i = 0; test_i < i; test_i++)
			result = signature_verify(m, sig, Q, curve);

		//Save time after verification
		clock_t end_verify = clock();

		//Clear variables
		mpz_clear(d);
		domain_parameters_clear(curve);
		signature_clear(sig);
		mpz_clear(m);

		//Save time before printing
		clock_t end = clock();

		//Print public key generation time
		fprintf(out, "%.4f, ", ((double) (start_sign - start_gen_Q)) / CLOCKS_PER_SEC);

		//Print signature generation time
		fprintf(out, "%.4f, ", ((double) (start_verify - start_sign)) / CLOCKS_PER_SEC);

		//Print signature verification time
		fprintf(out, "%.4f, ", ((double) (end_verify - start_verify)) / CLOCKS_PER_SEC);

		//Print operation time
		if(result)
			fprintf(out, "%.4f", ((double) (end - start)) / CLOCKS_PER_SEC);
		else
			fprintf(out, "-1");

		//print a new line
		fprintf(out, "\r\n");	//Acoording to RFC4180 this must be done with CLRF
	}
}
Exemplo n.º 5
0
static int dh_handshake(SSH_SESSION *session){
    STRING *e,*f,*pubkey,*signature;
    int ret;
    switch(session->dh_handshake_state){
        case DH_STATE_INIT:
            packet_clear_out(session);
            buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_INIT);
            dh_generate_x(session);
            dh_generate_e(session);
            e=dh_get_e(session);
            buffer_add_ssh_string(session->out_buffer,e);
            ret=packet_send(session);
            free(e);
            session->dh_handshake_state=DH_STATE_INIT_TO_SEND;
            if(ret==SSH_ERROR)
                return ret;
        case DH_STATE_INIT_TO_SEND:
            ret=packet_flush(session,0);
            if(ret!=SSH_OK)
                return ret; // SSH_ERROR or SSH_AGAIN
            session->dh_handshake_state=DH_STATE_INIT_SENT;
        case DH_STATE_INIT_SENT:
            ret=packet_wait(session,SSH2_MSG_KEXDH_REPLY,1);
            if(ret != SSH_OK)
                return ret;
            pubkey=buffer_get_ssh_string(session->in_buffer);
            if(!pubkey){
                ssh_set_error(session,SSH_FATAL,"No public key in packet");
                return SSH_ERROR;
            }
            dh_import_pubkey(session,pubkey);
            f=buffer_get_ssh_string(session->in_buffer);
            if(!f){
                ssh_set_error(session,SSH_FATAL,"No F number in packet");
                return SSH_ERROR;
            }
            dh_import_f(session,f);
            free(f);
            if(!(signature=buffer_get_ssh_string(session->in_buffer))){
                ssh_set_error(session,SSH_FATAL,"No signature in packet");
                return SSH_ERROR;
            }
            session->dh_server_signature=signature;
            dh_build_k(session);
            // send the MSG_NEWKEYS
            packet_clear_out(session);
            buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
            packet_send(session);
            session->dh_handshake_state=DH_STATE_NEWKEYS_TO_SEND;
        case DH_STATE_NEWKEYS_TO_SEND:
            ret=packet_flush(session,0);
            if(ret != SSH_OK)
                return ret;
            ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
            session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
        case DH_STATE_NEWKEYS_SENT:
            ret=packet_wait(session,SSH2_MSG_NEWKEYS,1);
            if(ret != SSH_OK)
                return ret;
            ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
            make_sessionid(session);
            /* set the cryptographic functions for the next crypto */
            /* (it is needed for generate_session_keys for key lenghts) */
            if(crypt_set_algorithms(session))
                return SSH_ERROR;
            generate_session_keys(session);
            /* verify the host's signature. XXX do it sooner */
            signature=session->dh_server_signature;
            session->dh_server_signature=NULL;
            if(signature_verify(session,signature)){
                free(signature);
                return SSH_ERROR;
            }
            free(signature);	/* forget it for now ... */
            /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
            if(session->current_crypto)
                crypto_free(session->current_crypto);
                /* XXX later, include a function to change keys */
            session->current_crypto=session->next_crypto;
            session->next_crypto=crypto_new();
            session->dh_handshake_state=DH_STATE_FINISHED;
            return SSH_OK;
        default:
            ssh_set_error(session,SSH_FATAL,"Invalid state in dh_handshake():%d",session->dh_handshake_state);
            return SSH_ERROR;
    }
    /* not reached */
    return SSH_ERROR;
}