xref: /titanic_52/usr/src/common/crypto/padding/pkcs7.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  * This is padding as decribed in Section 10.3 of RSA PKCS#7.
43*726fad2aSDina K Nimeh  *
44*726fad2aSDina K Nimeh  * The RSA PKCS Padding is in the following format:
45*726fad2aSDina K Nimeh  * +-----------------------------+----+-------------+
46*726fad2aSDina K Nimeh  * |       DATA                  |0x0k|0x0k|...|0x0k|
47*726fad2aSDina K Nimeh  * +-----------------------------+----+----+---+----+
48*726fad2aSDina K Nimeh  * where 0x0k is if data_len mod multiple = multiple - k
49*726fad2aSDina K Nimeh  * and multiple < 256 and 1 <= k <= multiple
50*726fad2aSDina K Nimeh  *
51*726fad2aSDina K Nimeh  * If databuf is non NULL, padbuf must be large enough
52*726fad2aSDina K Nimeh  * to contain both databuf and the padding.  databuf and
53*726fad2aSDina K Nimeh  * padbuf may be the same buffer.
54*726fad2aSDina K Nimeh  * databuf:
55*726fad2aSDina K Nimeh  * +-----------------------------+
56*726fad2aSDina K Nimeh  * |       DATA                  |
57*726fad2aSDina K Nimeh  * +-----------------------------+
58*726fad2aSDina K Nimeh  *                           datalen
59*726fad2aSDina K Nimeh  * padbuf:
60*726fad2aSDina K Nimeh  * +-----------------------------+----+-------------+
61*726fad2aSDina K Nimeh  * |       DATA                  |0x0k|0x0k|...|0x0k|
62*726fad2aSDina K Nimeh  * +-----------------------------+----+----+---+----+
63*726fad2aSDina K Nimeh  *                           datalen          padbuflen
64*726fad2aSDina K Nimeh  *
65*726fad2aSDina K Nimeh  * If databuf is NULL, padbuf only needs to be large
66*726fad2aSDina K Nimeh  * enough for the padding, and datalen must still be
67*726fad2aSDina K Nimeh  * provided to compute the padding value:
68*726fad2aSDina K Nimeh  *				 padbuf:
69*726fad2aSDina K Nimeh  *                               +----+-------------+
70*726fad2aSDina K Nimeh  *                               |0x0k|0x0k|...|0x0k|
71*726fad2aSDina K Nimeh  *                               +----+----+---+----+
72*726fad2aSDina K Nimeh  *                           datalen           padbuflen
73*726fad2aSDina K Nimeh  */
74*726fad2aSDina K Nimeh int
75*726fad2aSDina K Nimeh pkcs7_encode(uint8_t *databuf, size_t datalen, uint8_t *padbuf,
76*726fad2aSDina K Nimeh     size_t padbuflen, uint8_t multiple)
77*726fad2aSDina K Nimeh {
78*726fad2aSDina K Nimeh 	size_t	padlen;
79*726fad2aSDina K Nimeh 
80*726fad2aSDina K Nimeh 	padlen = multiple - (datalen % multiple);
81*726fad2aSDina K Nimeh 	if (databuf == NULL)
82*726fad2aSDina K Nimeh 		datalen = 0;
83*726fad2aSDina K Nimeh 
84*726fad2aSDina K Nimeh 	if (padlen > padbuflen - datalen) {
85*726fad2aSDina K Nimeh 		return (CKR_DATA_LEN_RANGE);
86*726fad2aSDina K Nimeh 	}
87*726fad2aSDina K Nimeh 
88*726fad2aSDina K Nimeh 	bcopy(databuf, padbuf, datalen);
89*726fad2aSDina K Nimeh 	(void) memset(padbuf + datalen, padlen & 0xff, padlen);
90*726fad2aSDina K Nimeh 
91*726fad2aSDina K Nimeh 	return (0);
92*726fad2aSDina K Nimeh }
93*726fad2aSDina K Nimeh 
94*726fad2aSDina K Nimeh /*
95*726fad2aSDina K Nimeh  * 'padbuf' points to the recovered message.  Strip off the padding and
96*726fad2aSDina K Nimeh  * validate it as much as possible.  'plen' is changed to hold the actual
97*726fad2aSDina K Nimeh  * data length.  'padbuf' is unchanged.
98*726fad2aSDina K Nimeh  */
99*726fad2aSDina K Nimeh int
100*726fad2aSDina K Nimeh pkcs7_decode(uint8_t *padbuf, size_t *plen)
101*726fad2aSDina K Nimeh {
102*726fad2aSDina K Nimeh 	int	i;
103*726fad2aSDina K Nimeh 	size_t	padlen;
104*726fad2aSDina K Nimeh 
105*726fad2aSDina K Nimeh 	/* Recover the padding value, even if padbuf has trailing nulls */
106*726fad2aSDina K Nimeh 	while (*plen > 0 && (padlen = padbuf[*plen - 1]) == 0)
107*726fad2aSDina K Nimeh 		(*plen)--;
108*726fad2aSDina K Nimeh 
109*726fad2aSDina K Nimeh 	/* Must have non-zero padding */
110*726fad2aSDina K Nimeh 	if (padlen == 0)
111*726fad2aSDina K Nimeh 		return (CKR_ENCRYPTED_DATA_INVALID);
112*726fad2aSDina K Nimeh 
113*726fad2aSDina K Nimeh 	/* Count back from all padding bytes; lint tag is for *plen-1-i >= 0 */
114*726fad2aSDina K Nimeh 	/* LINTED E_SUSPICIOUS_COMPARISON */
115*726fad2aSDina K Nimeh 	for (i = 0; i < padlen && (*plen - 1 - i) >= 0; i++) {
116*726fad2aSDina K Nimeh 		if (padbuf[*plen - 1 - i] != (padlen & 0xff))
117*726fad2aSDina K Nimeh 			return (CKR_ENCRYPTED_DATA_INVALID);
118*726fad2aSDina K Nimeh 	}
119*726fad2aSDina K Nimeh 	*plen -= i;
120*726fad2aSDina K Nimeh 	return (0);
121*726fad2aSDina K Nimeh }
122