1294328Sdes/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
257429Smarkm/*
357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi>
457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
557429Smarkm *                    All rights reserved
660576Skris *
765674Skris * As far as I am concerned, the code I have written for this software
865674Skris * can be used freely for any purpose.  Any derived versions of this
965674Skris * software must be clearly marked as such, and if the derived work is
1065674Skris * incompatible with the protocol description in the RFC file, it must be
1165674Skris * called by a name other than "ssh" or "Secure Shell".
1260576Skris *
1376262Sgreen *
1465674Skris * Copyright (c) 1999 Niels Provos.  All rights reserved.
1560576Skris *
1665674Skris * Redistribution and use in source and binary forms, with or without
1765674Skris * modification, are permitted provided that the following conditions
1865674Skris * are met:
1965674Skris * 1. Redistributions of source code must retain the above copyright
2065674Skris *    notice, this list of conditions and the following disclaimer.
2165674Skris * 2. Redistributions in binary form must reproduce the above copyright
2265674Skris *    notice, this list of conditions and the following disclaimer in the
2365674Skris *    documentation and/or other materials provided with the distribution.
2465674Skris *
2565674Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2665674Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2765674Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2865674Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2965674Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3065674Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3165674Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3265674Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3365674Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3465674Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3565674Skris *
3665674Skris *
3765674Skris * Description of the RSA algorithm can be found e.g. from the following
3865674Skris * sources:
3965674Skris *
4057429Smarkm *   Bruce Schneier: Applied Cryptography.  John Wiley & Sons, 1994.
4160576Skris *
4257429Smarkm *   Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
4357429Smarkm *   Computer Security.  Prentice-Hall, 1989.
4460576Skris *
4557429Smarkm *   Man Young Rhee: Cryptography and Secure Data Communications.  McGraw-Hill,
4657429Smarkm *   1994.
4760576Skris *
4857429Smarkm *   R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
4957429Smarkm *   System and Method.  US Patent 4,405,829, 1983.
5060576Skris *
5157429Smarkm *   Hans Riesel: Prime Numbers and Computer Methods for Factorization.
5257429Smarkm *   Birkhauser, 1994.
5360576Skris *
5465674Skris *   The RSA Frequently Asked Questions document by RSA Data Security,
5565674Skris *   Inc., 1995.
5660576Skris *
5765674Skris *   RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as
5865674Skris * included below:
5960576Skris *
6057429Smarkm *     [gone - had to be deleted - what a pity]
6165674Skris */
6257429Smarkm
6357429Smarkm#include "includes.h"
6457429Smarkm
65162856Sdes#include <sys/types.h>
66162856Sdes
67162856Sdes#include <stdarg.h>
68162856Sdes#include <string.h>
69162856Sdes
7057429Smarkm#include "rsa.h"
7176262Sgreen#include "log.h"
72294328Sdes#include "ssherr.h"
7357429Smarkm
74294328Sdesint
7557429Smarkmrsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
7657429Smarkm{
77294328Sdes	u_char *inbuf = NULL, *outbuf = NULL;
78294328Sdes	int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
7957429Smarkm
8057429Smarkm	if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
81294328Sdes		return SSH_ERR_INVALID_ARGUMENT;
8257429Smarkm
8357429Smarkm	olen = BN_num_bytes(key->n);
84294328Sdes	if ((outbuf = malloc(olen)) == NULL) {
85294328Sdes		r = SSH_ERR_ALLOC_FAIL;
86294328Sdes		goto out;
87294328Sdes	}
8857429Smarkm
8957429Smarkm	ilen = BN_num_bytes(in);
90294328Sdes	if ((inbuf = malloc(ilen)) == NULL) {
91294328Sdes		r = SSH_ERR_ALLOC_FAIL;
92294328Sdes		goto out;
93294328Sdes	}
9457429Smarkm	BN_bn2bin(in, inbuf);
9557429Smarkm
9657429Smarkm	if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
97294328Sdes	    RSA_PKCS1_PADDING)) <= 0) {
98294328Sdes		r = SSH_ERR_LIBCRYPTO_ERROR;
99294328Sdes		goto out;
100294328Sdes	}
10157429Smarkm
102294328Sdes	if (BN_bin2bn(outbuf, len, out) == NULL) {
103294328Sdes		r = SSH_ERR_LIBCRYPTO_ERROR;
104294328Sdes		goto out;
105294328Sdes	}
106294328Sdes	r = 0;
10757429Smarkm
108294328Sdes out:
109294328Sdes	if (outbuf != NULL) {
110294328Sdes		explicit_bzero(outbuf, olen);
111294328Sdes		free(outbuf);
112294328Sdes	}
113294328Sdes	if (inbuf != NULL) {
114294328Sdes		explicit_bzero(inbuf, ilen);
115294328Sdes		free(inbuf);
116294328Sdes	}
117294328Sdes	return r;
11857429Smarkm}
11957429Smarkm
12072397Skrisint
12157429Smarkmrsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
12257429Smarkm{
123294328Sdes	u_char *inbuf = NULL, *outbuf = NULL;
124294328Sdes	int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
12557429Smarkm
12657429Smarkm	olen = BN_num_bytes(key->n);
127294328Sdes	if ((outbuf = malloc(olen)) == NULL) {
128294328Sdes		r = SSH_ERR_ALLOC_FAIL;
129294328Sdes		goto out;
130294328Sdes	}
13157429Smarkm
13257429Smarkm	ilen = BN_num_bytes(in);
133294328Sdes	if ((inbuf = malloc(ilen)) == NULL) {
134294328Sdes		r = SSH_ERR_ALLOC_FAIL;
135294328Sdes		goto out;
136294328Sdes	}
13757429Smarkm	BN_bn2bin(in, inbuf);
13857429Smarkm
13957429Smarkm	if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
14072397Skris	    RSA_PKCS1_PADDING)) <= 0) {
141294328Sdes		r = SSH_ERR_LIBCRYPTO_ERROR;
142294328Sdes		goto out;
143294328Sdes	} else if (BN_bin2bn(outbuf, len, out) == NULL) {
144294328Sdes		r = SSH_ERR_LIBCRYPTO_ERROR;
145294328Sdes		goto out;
14672397Skris	}
147294328Sdes	r = 0;
148294328Sdes out:
149294328Sdes	if (outbuf != NULL) {
150294328Sdes		explicit_bzero(outbuf, olen);
151294328Sdes		free(outbuf);
152294328Sdes	}
153294328Sdes	if (inbuf != NULL) {
154294328Sdes		explicit_bzero(inbuf, ilen);
155294328Sdes		free(inbuf);
156294328Sdes	}
157294328Sdes	return r;
15857429Smarkm}
15957429Smarkm
16092559Sdes/* calculate p-1 and q-1 */
161294328Sdesint
16292559Sdesrsa_generate_additional_parameters(RSA *rsa)
16357429Smarkm{
164294328Sdes	BIGNUM *aux = NULL;
165294328Sdes	BN_CTX *ctx = NULL;
166294328Sdes	int r;
16776262Sgreen
16892559Sdes	if ((ctx = BN_CTX_new()) == NULL)
169294328Sdes		return SSH_ERR_ALLOC_FAIL;
170294328Sdes	if ((aux = BN_new()) == NULL) {
171294328Sdes		r = SSH_ERR_ALLOC_FAIL;
172294328Sdes		goto out;
173294328Sdes	}
17492559Sdes
175164149Sdes	if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
176164149Sdes	    (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
177164149Sdes	    (BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
178294328Sdes	    (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) {
179294328Sdes		r = SSH_ERR_LIBCRYPTO_ERROR;
180294328Sdes		goto out;
181294328Sdes	}
182294328Sdes	r = 0;
183294328Sdes out:
18476262Sgreen	BN_clear_free(aux);
18576262Sgreen	BN_CTX_free(ctx);
186294328Sdes	return r;
18757429Smarkm}
18876262Sgreen
189