xref: /titanic_52/usr/src/common/crypto/padding/pkcs1.c (revision 726fad2a65f16c200a03969c29cb5c86c2d427db)
1*726fad2aSDina K Nimeh /*
2*726fad2aSDina K Nimeh  * CDDL HEADER START
3*726fad2aSDina K Nimeh  *
4*726fad2aSDina K Nimeh  * The contents of this file are subject to the terms of the
5*726fad2aSDina K Nimeh  * Common Development and Distribution License (the "License").
6*726fad2aSDina K Nimeh  * You may not use this file except in compliance with the License.
7*726fad2aSDina K Nimeh  *
8*726fad2aSDina K Nimeh  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*726fad2aSDina K Nimeh  * or http://www.opensolaris.org/os/licensing.
10*726fad2aSDina K Nimeh  * See the License for the specific language governing permissions
11*726fad2aSDina K Nimeh  * and limitations under the License.
12*726fad2aSDina K Nimeh  *
13*726fad2aSDina K Nimeh  * When distributing Covered Code, include this CDDL HEADER in each
14*726fad2aSDina K Nimeh  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*726fad2aSDina K Nimeh  * If applicable, add the following below this CDDL HEADER, with the
16*726fad2aSDina K Nimeh  * fields enclosed by brackets "[]" replaced with your own identifying
17*726fad2aSDina K Nimeh  * information: Portions Copyright [yyyy] [name of copyright owner]
18*726fad2aSDina K Nimeh  *
19*726fad2aSDina K Nimeh  * CDDL HEADER END
20*726fad2aSDina K Nimeh  */
21*726fad2aSDina K Nimeh 
22*726fad2aSDina K Nimeh /*
23*726fad2aSDina K Nimeh  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*726fad2aSDina K Nimeh  */
25*726fad2aSDina K Nimeh 
26*726fad2aSDina K Nimeh /*
27*726fad2aSDina K Nimeh  * This file contains padding helper routines common to
28*726fad2aSDina K Nimeh  * the PKCS11 soft token code and the kernel crypto code.
29*726fad2aSDina K Nimeh  */
30*726fad2aSDina K Nimeh 
31*726fad2aSDina K Nimeh #include <sys/types.h>
32*726fad2aSDina K Nimeh #include "padding.h"
33*726fad2aSDina K Nimeh 
34*726fad2aSDina K Nimeh #ifdef _KERNEL
35*726fad2aSDina K Nimeh #include <sys/param.h>
36*726fad2aSDina K Nimeh #else
37*726fad2aSDina K Nimeh #include <strings.h>
38*726fad2aSDina K Nimeh #include <cryptoutil.h>
39*726fad2aSDina K Nimeh #endif
40*726fad2aSDina K Nimeh 
41*726fad2aSDina K Nimeh /*
42*726fad2aSDina K Nimeh  * To create a block type "02" encryption block for RSA PKCS encryption
43*726fad2aSDina K Nimeh  * process.
44*726fad2aSDina K Nimeh  *
45*726fad2aSDina K Nimeh  * This is EME-PKCS1-v1_5 encoding as described in RSA PKCS#1.
46*726fad2aSDina K Nimeh  *
47*726fad2aSDina K Nimeh  * The RSA PKCS Padding before encryption is in the following format:
48*726fad2aSDina K Nimeh  * +----+----+--------------------+----+-----------------------------+
49*726fad2aSDina K Nimeh  * |0x00|0x02| 8 bytes or more RN |0x00|       DATA                  |
50*726fad2aSDina K Nimeh  * +----+----+--------------------+----+-----------------------------+
51*726fad2aSDina K Nimeh  *
52*726fad2aSDina K Nimeh  *
53*726fad2aSDina K Nimeh  * To create a block type "01" block for RSA PKCS signature process.
54*726fad2aSDina K Nimeh  *
55*726fad2aSDina K Nimeh  * This EMSA-PKCS1-1_5 encoding as decribed in RSA PKCS#1.
56*726fad2aSDina K Nimeh  *
57*726fad2aSDina K Nimeh  * The RSA PKCS Padding before Signing is in the following format:
58*726fad2aSDina K Nimeh  * +----+----+----------------------+----+-----------------------------+
59*726fad2aSDina K Nimeh  * |0x00|0x01| 8 bytes of more 0xFF |0x00|          DATA               |
60*726fad2aSDina K Nimeh  * +----+----+----------------------+----+-----------------------------+
61*726fad2aSDina K Nimeh  *
62*726fad2aSDina K Nimeh  */
63*726fad2aSDina K Nimeh int
64*726fad2aSDina K Nimeh pkcs1_encode(int method, uint8_t *databuf, size_t datalen, uint8_t *padbuf,
65*726fad2aSDina K Nimeh     size_t padbuflen)
66*726fad2aSDina K Nimeh {
67*726fad2aSDina K Nimeh 	size_t	padlen;
68*726fad2aSDina K Nimeh 	int	rv;
69*726fad2aSDina K Nimeh 
70*726fad2aSDina K Nimeh 	padlen = padbuflen - datalen;
71*726fad2aSDina K Nimeh 	if (padlen < MIN_PKCS1_PADLEN) {
72*726fad2aSDina K Nimeh 		return (CKR_DATA_LEN_RANGE);
73*726fad2aSDina K Nimeh 	}
74*726fad2aSDina K Nimeh 
75*726fad2aSDina K Nimeh 	rv = 0;
76*726fad2aSDina K Nimeh 
77*726fad2aSDina K Nimeh 	padbuf[0] = 0x00;
78*726fad2aSDina K Nimeh 	padbuf[1] = (method == PKCS1_ENCRYPT) ? 0x02 : 0x01;
79*726fad2aSDina K Nimeh 
80*726fad2aSDina K Nimeh 	if (method == PKCS1_ENCRYPT) {
81*726fad2aSDina K Nimeh #ifdef _KERNEL
82*726fad2aSDina K Nimeh 		rv = knzero_random_generator(padbuf + 2, padlen - 3);
83*726fad2aSDina K Nimeh #else
84*726fad2aSDina K Nimeh 		rv = (pkcs11_get_nzero_urandom(padbuf + 2, padlen - 3) < 0) ?
85*726fad2aSDina K Nimeh 		    CKR_DEVICE_ERROR : 0;
86*726fad2aSDina K Nimeh #endif
87*726fad2aSDina K Nimeh 	} else if (method == PKCS1_SIGN) {
88*726fad2aSDina K Nimeh #ifdef _KERNEL
89*726fad2aSDina K Nimeh 		kmemset(padbuf + 2, 0xFF, padlen - 3);
90*726fad2aSDina K Nimeh #else
91*726fad2aSDina K Nimeh 		(void) memset(padbuf + 2, 0xFF, padlen - 3);
92*726fad2aSDina K Nimeh #endif
93*726fad2aSDina K Nimeh 	}
94*726fad2aSDina K Nimeh 
95*726fad2aSDina K Nimeh 	if (rv != 0) {
96*726fad2aSDina K Nimeh 		return (rv);
97*726fad2aSDina K Nimeh 	}
98*726fad2aSDina K Nimeh 
99*726fad2aSDina K Nimeh 	padbuf[padlen - 1] = 0x00;
100*726fad2aSDina K Nimeh 
101*726fad2aSDina K Nimeh 	bcopy(databuf, padbuf + padlen, datalen);
102*726fad2aSDina K Nimeh 
103*726fad2aSDina K Nimeh 	return (0);
104*726fad2aSDina K Nimeh }
105*726fad2aSDina K Nimeh 
106*726fad2aSDina K Nimeh /*
107*726fad2aSDina K Nimeh  * The RSA PKCS Padding in the following format:
108*726fad2aSDina K Nimeh  * +----+----+-------------------------+----+------------------------+
109*726fad2aSDina K Nimeh  * |0x00| BT | 8 bytes or more padding |0x00|       DATA             |
110*726fad2aSDina K Nimeh  * +----+----+-+++++-------------------+----+------------------------+
111*726fad2aSDina K Nimeh  * where BT is block type: 0x02 for encrypt/decrypt, 0x01 for sign/verify
112*726fad2aSDina K Nimeh  *
113*726fad2aSDina K Nimeh  * 'padbuf' points to the recovered message.  Strip off the padding and
114*726fad2aSDina K Nimeh  * validate it as much as possible.  'plen' is changed to hold the actual
115*726fad2aSDina K Nimeh  * data length.
116*726fad2aSDina K Nimeh  */
117*726fad2aSDina K Nimeh int
118*726fad2aSDina K Nimeh pkcs1_decode(int method, uint8_t *padbuf, size_t *plen)
119*726fad2aSDina K Nimeh {
120*726fad2aSDina K Nimeh 	int	rv = ((method == PKCS1_DECRYPT) ? CKR_ENCRYPTED_DATA_INVALID :
121*726fad2aSDina K Nimeh 	    CKR_SIGNATURE_INVALID);
122*726fad2aSDina K Nimeh 	int	i;
123*726fad2aSDina K Nimeh 
124*726fad2aSDina K Nimeh 	/* Check to see if the recovered data is padded is 0x0002 or 0x0001. */
125*726fad2aSDina K Nimeh 	if (padbuf[0] != 0x00 || padbuf[1] != (method == PKCS1_DECRYPT ?
126*726fad2aSDina K Nimeh 	    0x02 : 0x01)) {
127*726fad2aSDina K Nimeh 		return (rv);
128*726fad2aSDina K Nimeh 	}
129*726fad2aSDina K Nimeh 
130*726fad2aSDina K Nimeh 	/* Remove all the random bits up to 0x00 (= NULL char) */
131*726fad2aSDina K Nimeh 	for (i = 2; (*plen - i) > 0; i++) {
132*726fad2aSDina K Nimeh 		if (padbuf[i] == 0x00) {
133*726fad2aSDina K Nimeh 			i++;
134*726fad2aSDina K Nimeh 			if (i < MIN_PKCS1_PADLEN) {
135*726fad2aSDina K Nimeh 				return (rv);
136*726fad2aSDina K Nimeh 			}
137*726fad2aSDina K Nimeh 			*plen -= i;
138*726fad2aSDina K Nimeh 
139*726fad2aSDina K Nimeh 			return (0);
140*726fad2aSDina K Nimeh 		} else if (method == PKCS1_VERIFY && padbuf[i] != 0xFF) {
141*726fad2aSDina K Nimeh 			return (rv);
142*726fad2aSDina K Nimeh 		}
143*726fad2aSDina K Nimeh 	}
144*726fad2aSDina K Nimeh 
145*726fad2aSDina K Nimeh 	return (rv);
146*726fad2aSDina K Nimeh }
147