1*658eb9e1SMichael Kruse /*
2*658eb9e1SMichael Kruse Name: rsamath.c
3*658eb9e1SMichael Kruse Purpose: Implements part of PKCS#1, v. 2.1, June 14, 2002 (RSA Labs)
4*658eb9e1SMichael Kruse Author: M. J. Fromberger
5*658eb9e1SMichael Kruse
6*658eb9e1SMichael Kruse Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
7*658eb9e1SMichael Kruse
8*658eb9e1SMichael Kruse Permission is hereby granted, free of charge, to any person obtaining a copy
9*658eb9e1SMichael Kruse of this software and associated documentation files (the "Software"), to deal
10*658eb9e1SMichael Kruse in the Software without restriction, including without limitation the rights
11*658eb9e1SMichael Kruse to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12*658eb9e1SMichael Kruse copies of the Software, and to permit persons to whom the Software is
13*658eb9e1SMichael Kruse furnished to do so, subject to the following conditions:
14*658eb9e1SMichael Kruse
15*658eb9e1SMichael Kruse The above copyright notice and this permission notice shall be included in
16*658eb9e1SMichael Kruse all copies or substantial portions of the Software.
17*658eb9e1SMichael Kruse
18*658eb9e1SMichael Kruse THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*658eb9e1SMichael Kruse IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*658eb9e1SMichael Kruse FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21*658eb9e1SMichael Kruse AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*658eb9e1SMichael Kruse LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*658eb9e1SMichael Kruse OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24*658eb9e1SMichael Kruse SOFTWARE.
25*658eb9e1SMichael Kruse */
26*658eb9e1SMichael Kruse
27*658eb9e1SMichael Kruse #include "rsamath.h"
28*658eb9e1SMichael Kruse
29*658eb9e1SMichael Kruse #include <limits.h>
30*658eb9e1SMichael Kruse #include <string.h>
31*658eb9e1SMichael Kruse
32*658eb9e1SMichael Kruse static mp_result s_rsa_transform(mp_int msg, mp_int exp, mp_int mod,
33*658eb9e1SMichael Kruse mp_int out);
34*658eb9e1SMichael Kruse
35*658eb9e1SMichael Kruse /* Convert integer to octet string, per PKCS#1 v.2.1 */
rsa_i2osp(mp_int z,unsigned char * out,int len)36*658eb9e1SMichael Kruse mp_result rsa_i2osp(mp_int z, unsigned char *out, int len) {
37*658eb9e1SMichael Kruse int excess_len = mp_int_binary_len(z);
38*658eb9e1SMichael Kruse
39*658eb9e1SMichael Kruse if (excess_len < len) return MP_RANGE;
40*658eb9e1SMichael Kruse
41*658eb9e1SMichael Kruse memset(out, 0, len);
42*658eb9e1SMichael Kruse
43*658eb9e1SMichael Kruse excess_len -= len;
44*658eb9e1SMichael Kruse mp_int_to_binary(z, out + excess_len, len);
45*658eb9e1SMichael Kruse
46*658eb9e1SMichael Kruse return MP_OK;
47*658eb9e1SMichael Kruse }
48*658eb9e1SMichael Kruse
49*658eb9e1SMichael Kruse /* Convert octet string to integer, per PKCS#1 v.2.1 */
rsa_os2ip(mp_int z,unsigned char * in,int len)50*658eb9e1SMichael Kruse mp_result rsa_os2ip(mp_int z, unsigned char *in, int len) {
51*658eb9e1SMichael Kruse return mp_int_read_binary(z, in, len);
52*658eb9e1SMichael Kruse }
53*658eb9e1SMichael Kruse
54*658eb9e1SMichael Kruse /* Primitive RSA encryption operation */
rsa_rsaep(mp_int msg,mp_int exp,mp_int mod,mp_int cipher)55*658eb9e1SMichael Kruse mp_result rsa_rsaep(mp_int msg, mp_int exp, mp_int mod, mp_int cipher) {
56*658eb9e1SMichael Kruse return s_rsa_transform(msg, exp, mod, cipher);
57*658eb9e1SMichael Kruse }
58*658eb9e1SMichael Kruse
59*658eb9e1SMichael Kruse /* Primitive RSA decryption operation */
rsa_rsadp(mp_int cipher,mp_int exp,mp_int mod,mp_int msg)60*658eb9e1SMichael Kruse mp_result rsa_rsadp(mp_int cipher, mp_int exp, mp_int mod, mp_int msg) {
61*658eb9e1SMichael Kruse return s_rsa_transform(cipher, exp, mod, msg);
62*658eb9e1SMichael Kruse }
63*658eb9e1SMichael Kruse
64*658eb9e1SMichael Kruse /* Primitive RSA signing operation */
rsa_rsasp(mp_int msg,mp_int exp,mp_int mod,mp_int signature)65*658eb9e1SMichael Kruse mp_result rsa_rsasp(mp_int msg, mp_int exp, mp_int mod, mp_int signature) {
66*658eb9e1SMichael Kruse return s_rsa_transform(msg, exp, mod, signature);
67*658eb9e1SMichael Kruse }
68*658eb9e1SMichael Kruse
69*658eb9e1SMichael Kruse /* Primitive RSA verification operation */
rsa_rsavp(mp_int signature,mp_int exp,mp_int mod,mp_int msg)70*658eb9e1SMichael Kruse mp_result rsa_rsavp(mp_int signature, mp_int exp, mp_int mod, mp_int msg) {
71*658eb9e1SMichael Kruse return s_rsa_transform(signature, exp, mod, msg);
72*658eb9e1SMichael Kruse }
73*658eb9e1SMichael Kruse
74*658eb9e1SMichael Kruse /* Compute the maximum length in bytes a message can have using PKCS#1
75*658eb9e1SMichael Kruse v.1.5 encoding with the given modulus */
rsa_max_message_len(mp_int mod)76*658eb9e1SMichael Kruse int rsa_max_message_len(mp_int mod) {
77*658eb9e1SMichael Kruse int num_bits = mp_int_count_bits(mod);
78*658eb9e1SMichael Kruse int num_bytes = num_bits / CHAR_BIT;
79*658eb9e1SMichael Kruse
80*658eb9e1SMichael Kruse if (num_bytes < 11) {
81*658eb9e1SMichael Kruse return 0; /* at least eleven bytes are required for padding */
82*658eb9e1SMichael Kruse } else {
83*658eb9e1SMichael Kruse return num_bytes - 11;
84*658eb9e1SMichael Kruse }
85*658eb9e1SMichael Kruse }
86*658eb9e1SMichael Kruse
rsa_pkcs1v15_encode(unsigned char * buf,int msg_len,int buf_len,int tag,random_f filler)87*658eb9e1SMichael Kruse mp_result rsa_pkcs1v15_encode(unsigned char *buf, int msg_len, int buf_len,
88*658eb9e1SMichael Kruse int tag, random_f filler) {
89*658eb9e1SMichael Kruse /* Make sure there is enough space for the encoded output */
90*658eb9e1SMichael Kruse if (msg_len > (buf_len - 11)) return MP_RANGE;
91*658eb9e1SMichael Kruse
92*658eb9e1SMichael Kruse int msg_start = buf_len - msg_len;
93*658eb9e1SMichael Kruse int pad_len = msg_start - 3;
94*658eb9e1SMichael Kruse
95*658eb9e1SMichael Kruse /* Move message to top of buffer -- these might overlap, so we rely
96*658eb9e1SMichael Kruse on the semantics of memmove() here */
97*658eb9e1SMichael Kruse memmove(buf + msg_start, buf, msg_len);
98*658eb9e1SMichael Kruse
99*658eb9e1SMichael Kruse /* Set initial bytes as required by the specification */
100*658eb9e1SMichael Kruse buf[0] = 0x00;
101*658eb9e1SMichael Kruse buf[1] = (unsigned char)tag;
102*658eb9e1SMichael Kruse
103*658eb9e1SMichael Kruse /* Fill with random padding. We'll just assume the filler function
104*658eb9e1SMichael Kruse does the right thing and only writes the requested number of
105*658eb9e1SMichael Kruse nonzero bytes */
106*658eb9e1SMichael Kruse (filler)(buf + 2, pad_len);
107*658eb9e1SMichael Kruse
108*658eb9e1SMichael Kruse /* Write separator between pad and message body */
109*658eb9e1SMichael Kruse buf[msg_start - 1] = 0x00;
110*658eb9e1SMichael Kruse
111*658eb9e1SMichael Kruse return MP_OK;
112*658eb9e1SMichael Kruse }
113*658eb9e1SMichael Kruse
rsa_pkcs1v15_decode(unsigned char * buf,int buf_len,int tag,int * msg_len)114*658eb9e1SMichael Kruse mp_result rsa_pkcs1v15_decode(unsigned char *buf, int buf_len, int tag,
115*658eb9e1SMichael Kruse int *msg_len) {
116*658eb9e1SMichael Kruse /* Make sure the buffer is syntactically valid */
117*658eb9e1SMichael Kruse if (buf_len < 11 || buf[0] != 0x00 || buf[1] != (unsigned char)tag)
118*658eb9e1SMichael Kruse return MP_UNDEF;
119*658eb9e1SMichael Kruse
120*658eb9e1SMichael Kruse /* Figure out how many bytes of random padding there are */
121*658eb9e1SMichael Kruse int i = 2;
122*658eb9e1SMichael Kruse int pad_len = 0;
123*658eb9e1SMichael Kruse while (buf[i++] != '\0') ++pad_len;
124*658eb9e1SMichael Kruse
125*658eb9e1SMichael Kruse int data_start = i;
126*658eb9e1SMichael Kruse int data_len = buf_len - data_start;
127*658eb9e1SMichael Kruse
128*658eb9e1SMichael Kruse /* Shift the message to the front of the buffer */
129*658eb9e1SMichael Kruse memmove(buf, buf + data_start, data_len);
130*658eb9e1SMichael Kruse
131*658eb9e1SMichael Kruse /* Zero out the rest of the buffer */
132*658eb9e1SMichael Kruse memset(buf + data_len, 0, pad_len + 3);
133*658eb9e1SMichael Kruse
134*658eb9e1SMichael Kruse *msg_len = data_len;
135*658eb9e1SMichael Kruse
136*658eb9e1SMichael Kruse return MP_OK;
137*658eb9e1SMichael Kruse }
138*658eb9e1SMichael Kruse
s_rsa_transform(mp_int msg,mp_int exp,mp_int mod,mp_int out)139*658eb9e1SMichael Kruse static mp_result s_rsa_transform(mp_int msg, mp_int exp, mp_int mod,
140*658eb9e1SMichael Kruse mp_int out) {
141*658eb9e1SMichael Kruse if (mp_int_compare_zero(msg) < 0 || mp_int_compare(msg, mod) >= 0) {
142*658eb9e1SMichael Kruse return MP_RANGE;
143*658eb9e1SMichael Kruse }
144*658eb9e1SMichael Kruse
145*658eb9e1SMichael Kruse return mp_int_exptmod(msg, exp, mod, out);
146*658eb9e1SMichael Kruse }
147*658eb9e1SMichael Kruse
148*658eb9e1SMichael Kruse /* Here there be dragons */
149