⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose.  Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "includes.h"RCSID("$OpenBSD: key.c,v 1.44 2002/05/31 13:16:48 markus Exp $");#include <openssl/evp.h>#include "xmalloc.h"#include "key.h"#include "rsa.h"#include "ssh-dss.h"#include "ssh-rsa.h"#include "uuencode.h"#include "buffer.h"#include "bufaux.h"#include "log.h"Key *key_new(int type){	Key *k;	RSA *rsa;	DSA *dsa;	k = xmalloc(sizeof(*k));	k->type = type;	k->flags = 0;	k->dsa = NULL;	k->rsa = NULL;	switch (k->type) {	case KEY_RSA1:	case KEY_RSA:		if ((rsa = RSA_new()) == NULL)			fatal("key_new: RSA_new failed");		if ((rsa->n = BN_new()) == NULL)			fatal("key_new: BN_new failed");		if ((rsa->e = BN_new()) == NULL)			fatal("key_new: BN_new failed");		k->rsa = rsa;		break;	case KEY_DSA:		if ((dsa = DSA_new()) == NULL)			fatal("key_new: DSA_new failed");		if ((dsa->p = BN_new()) == NULL)			fatal("key_new: BN_new failed");		if ((dsa->q = BN_new()) == NULL)			fatal("key_new: BN_new failed");		if ((dsa->g = BN_new()) == NULL)			fatal("key_new: BN_new failed");		if ((dsa->pub_key = BN_new()) == NULL)			fatal("key_new: BN_new failed");		k->dsa = dsa;		break;	case KEY_UNSPEC:		break;	default:		fatal("key_new: bad key type %d", k->type);		break;	}	return k;}Key *key_new_private(int type){	Key *k = key_new(type);	switch (k->type) {	case KEY_RSA1:	case KEY_RSA:		if ((k->rsa->d = BN_new()) == NULL)			fatal("key_new_private: BN_new failed");		if ((k->rsa->iqmp = BN_new()) == NULL)			fatal("key_new_private: BN_new failed");		if ((k->rsa->q = BN_new()) == NULL)			fatal("key_new_private: BN_new failed");		if ((k->rsa->p = BN_new()) == NULL)			fatal("key_new_private: BN_new failed");		if ((k->rsa->dmq1 = BN_new()) == NULL)			fatal("key_new_private: BN_new failed");		if ((k->rsa->dmp1 = BN_new()) == NULL)			fatal("key_new_private: BN_new failed");		break;	case KEY_DSA:		if ((k->dsa->priv_key = BN_new()) == NULL)			fatal("key_new_private: BN_new failed");		break;	case KEY_UNSPEC:		break;	default:		break;	}	return k;}voidkey_free(Key *k){	switch (k->type) {	case KEY_RSA1:	case KEY_RSA:		if (k->rsa != NULL)			RSA_free(k->rsa);		k->rsa = NULL;		break;	case KEY_DSA:		if (k->dsa != NULL)			DSA_free(k->dsa);		k->dsa = NULL;		break;	case KEY_UNSPEC:		break;	default:		fatal("key_free: bad key type %d", k->type);		break;	}	xfree(k);}intkey_equal(Key *a, Key *b){	if (a == NULL || b == NULL || a->type != b->type)		return 0;	switch (a->type) {	case KEY_RSA1:	case KEY_RSA:		return a->rsa != NULL && b->rsa != NULL &&		    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&		    BN_cmp(a->rsa->n, b->rsa->n) == 0;		break;	case KEY_DSA:		return a->dsa != NULL && b->dsa != NULL &&		    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&		    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;		break;	default:		fatal("key_equal: bad key type %d", a->type);		break;	}	return 0;}static u_char*key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length){	const EVP_MD *md = NULL;	EVP_MD_CTX ctx;	u_char *blob = NULL;	u_char *retval = NULL;	u_int len = 0;	int nlen, elen;	*dgst_raw_length = 0;	switch (dgst_type) {	case SSH_FP_MD5:		md = EVP_md5();		break;	case SSH_FP_SHA1:		md = EVP_sha1();		break;	default:		fatal("key_fingerprint_raw: bad digest type %d",		    dgst_type);	}	switch (k->type) {	case KEY_RSA1:		nlen = BN_num_bytes(k->rsa->n);		elen = BN_num_bytes(k->rsa->e);		len = nlen + elen;		blob = xmalloc(len);		BN_bn2bin(k->rsa->n, blob);		BN_bn2bin(k->rsa->e, blob + nlen);		break;	case KEY_DSA:	case KEY_RSA:		key_to_blob(k, &blob, &len);		break;	case KEY_UNSPEC:		return retval;		break;	default:		fatal("key_fingerprint_raw: bad key type %d", k->type);		break;	}	if (blob != NULL) {		retval = xmalloc(EVP_MAX_MD_SIZE);		EVP_DigestInit(&ctx, md);		EVP_DigestUpdate(&ctx, blob, len);		EVP_DigestFinal(&ctx, retval, dgst_raw_length);		memset(blob, 0, len);		xfree(blob);	} else {		fatal("key_fingerprint_raw: blob is null");	}	return retval;}static char*key_fingerprint_hex(u_char* dgst_raw, u_int dgst_raw_len){	char *retval;	int i;	retval = xmalloc(dgst_raw_len * 3 + 1);	retval[0] = '\0';	for (i = 0; i < dgst_raw_len; i++) {		char hex[4];		snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);		strlcat(retval, hex, dgst_raw_len * 3);	}	retval[(dgst_raw_len * 3) - 1] = '\0';	return retval;}static char*key_fingerprint_bubblebabble(u_char* dgst_raw, u_int dgst_raw_len){	char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };	char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',	    'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };	u_int i, j = 0, rounds, seed = 1;	char *retval;	rounds = (dgst_raw_len / 2) + 1;	retval = xmalloc(sizeof(char) * (rounds*6));	retval[j++] = 'x';	for (i = 0; i < rounds; i++) {		u_int idx0, idx1, idx2, idx3, idx4;		if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {			idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +			    seed) % 6;			idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;			idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +			    (seed / 6)) % 6;			retval[j++] = vowels[idx0];			retval[j++] = consonants[idx1];			retval[j++] = vowels[idx2];			if ((i + 1) < rounds) {				idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;				idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;				retval[j++] = consonants[idx3];				retval[j++] = '-';				retval[j++] = consonants[idx4];				seed = ((seed * 5) +				    ((((u_int)(dgst_raw[2 * i])) * 7) +				    ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;			}		} else {			idx0 = seed % 6;			idx1 = 16;			idx2 = seed / 6;			retval[j++] = vowels[idx0];			retval[j++] = consonants[idx1];			retval[j++] = vowels[idx2];		}	}	retval[j++] = 'x';	retval[j++] = '\0';	return retval;}char*key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep){	char *retval = NULL;	u_char *dgst_raw;	u_int dgst_raw_len;	dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);	if (!dgst_raw)		fatal("key_fingerprint: null from key_fingerprint_raw()");	switch (dgst_rep) {	case SSH_FP_HEX:		retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);		break;	case SSH_FP_BUBBLEBABBLE:		retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);		break;	default:		fatal("key_fingerprint_ex: bad digest representation %d",		    dgst_rep);		break;	}	memset(dgst_raw, 0, dgst_raw_len);	xfree(dgst_raw);	return retval;}/* * Reads a multiple-precision integer in decimal from the buffer, and advances * the pointer.  The integer must already be initialized.  This function is * permitted to modify the buffer.  This leaves *cpp to point just beyond the * last processed (and maybe modified) character.  Note that this may modify * the buffer containing the number. */static intread_bignum(char **cpp, BIGNUM * value){	char *cp = *cpp;	int old;	/* Skip any leading whitespace. */	for (; *cp == ' ' || *cp == '\t'; cp++)		;	/* Check that it begins with a decimal digit. */	if (*cp < '0' || *cp > '9')		return 0;	/* Save starting position. */	*cpp = cp;	/* Move forward until all decimal digits skipped. */	for (; *cp >= '0' && *cp <= '9'; cp++)		;	/* Save the old terminating character, and replace it by \0. */	old = *cp;	*cp = 0;	/* Parse the number. */	if (BN_dec2bn(&value, *cpp) == 0)		return 0;	/* Restore old terminating character. */	*cp = old;	/* Move beyond the number and return success. */	*cpp = cp;	return 1;}static intwrite_bignum(FILE *f, BIGNUM *num){	char *buf = BN_bn2dec(num);	if (buf == NULL) {		error("write_bignum: BN_bn2dec() failed");		return 0;	}	fprintf(f, " %s", buf);	OPENSSL_free(buf);	return 1;}/* returns 1 ok, -1 error */intkey_read(Key *ret, char **cpp){	Key *k;	int success = -1;	char *cp, *space;	int len, n, type;	u_int bits;	u_char *blob;	cp = *cpp;	switch (ret->type) {	case KEY_RSA1:		/* Get number of bits. */		if (*cp < '0' || *cp > '9')			return -1;	/* Bad bit count... */		for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)			bits = 10 * bits + *cp - '0';		if (bits == 0)			return -1;		*cpp = cp;		/* Get public exponent, public modulus. */		if (!read_bignum(cpp, ret->rsa->e))			return -1;		if (!read_bignum(cpp, ret->rsa->n))			return -1;		success = 1;		break;	case KEY_UNSPEC:	case KEY_RSA:	case KEY_DSA:		space = strchr(cp, ' ');		if (space == NULL) {			debug3("key_read: no space");			return -1;		}		*space = '\0';		type = key_type_from_name(cp);		*space = ' ';		if (type == KEY_UNSPEC) {			debug3("key_read: no key found");			return -1;		}		cp = space+1;		if (*cp == '\0') {			debug3("key_read: short string");			return -1;		}		if (ret->type == KEY_UNSPEC) {			ret->type = type;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -