summaryrefslogtreecommitdiff
path: root/usr/src/common/crypto/padding/pkcs1.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common/crypto/padding/pkcs1.c')
-rw-r--r--usr/src/common/crypto/padding/pkcs1.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/usr/src/common/crypto/padding/pkcs1.c b/usr/src/common/crypto/padding/pkcs1.c
new file mode 100644
index 0000000000..c7e4970d72
--- /dev/null
+++ b/usr/src/common/crypto/padding/pkcs1.c
@@ -0,0 +1,146 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * This file contains padding helper routines common to
+ * the PKCS11 soft token code and the kernel crypto code.
+ */
+
+#include <sys/types.h>
+#include "padding.h"
+
+#ifdef _KERNEL
+#include <sys/param.h>
+#else
+#include <strings.h>
+#include <cryptoutil.h>
+#endif
+
+/*
+ * To create a block type "02" encryption block for RSA PKCS encryption
+ * process.
+ *
+ * This is EME-PKCS1-v1_5 encoding as described in RSA PKCS#1.
+ *
+ * The RSA PKCS Padding before encryption is in the following format:
+ * +----+----+--------------------+----+-----------------------------+
+ * |0x00|0x02| 8 bytes or more RN |0x00| DATA |
+ * +----+----+--------------------+----+-----------------------------+
+ *
+ *
+ * To create a block type "01" block for RSA PKCS signature process.
+ *
+ * This EMSA-PKCS1-1_5 encoding as decribed in RSA PKCS#1.
+ *
+ * The RSA PKCS Padding before Signing is in the following format:
+ * +----+----+----------------------+----+-----------------------------+
+ * |0x00|0x01| 8 bytes of more 0xFF |0x00| DATA |
+ * +----+----+----------------------+----+-----------------------------+
+ *
+ */
+int
+pkcs1_encode(int method, uint8_t *databuf, size_t datalen, uint8_t *padbuf,
+ size_t padbuflen)
+{
+ size_t padlen;
+ int rv;
+
+ padlen = padbuflen - datalen;
+ if (padlen < MIN_PKCS1_PADLEN) {
+ return (CKR_DATA_LEN_RANGE);
+ }
+
+ rv = 0;
+
+ padbuf[0] = 0x00;
+ padbuf[1] = (method == PKCS1_ENCRYPT) ? 0x02 : 0x01;
+
+ if (method == PKCS1_ENCRYPT) {
+#ifdef _KERNEL
+ rv = knzero_random_generator(padbuf + 2, padlen - 3);
+#else
+ rv = (pkcs11_get_nzero_urandom(padbuf + 2, padlen - 3) < 0) ?
+ CKR_DEVICE_ERROR : 0;
+#endif
+ } else if (method == PKCS1_SIGN) {
+#ifdef _KERNEL
+ kmemset(padbuf + 2, 0xFF, padlen - 3);
+#else
+ (void) memset(padbuf + 2, 0xFF, padlen - 3);
+#endif
+ }
+
+ if (rv != 0) {
+ return (rv);
+ }
+
+ padbuf[padlen - 1] = 0x00;
+
+ bcopy(databuf, padbuf + padlen, datalen);
+
+ return (0);
+}
+
+/*
+ * The RSA PKCS Padding in the following format:
+ * +----+----+-------------------------+----+------------------------+
+ * |0x00| BT | 8 bytes or more padding |0x00| DATA |
+ * +----+----+-+++++-------------------+----+------------------------+
+ * where BT is block type: 0x02 for encrypt/decrypt, 0x01 for sign/verify
+ *
+ * 'padbuf' points to the recovered message. Strip off the padding and
+ * validate it as much as possible. 'plen' is changed to hold the actual
+ * data length.
+ */
+int
+pkcs1_decode(int method, uint8_t *padbuf, size_t *plen)
+{
+ int rv = ((method == PKCS1_DECRYPT) ? CKR_ENCRYPTED_DATA_INVALID :
+ CKR_SIGNATURE_INVALID);
+ int i;
+
+ /* Check to see if the recovered data is padded is 0x0002 or 0x0001. */
+ if (padbuf[0] != 0x00 || padbuf[1] != (method == PKCS1_DECRYPT ?
+ 0x02 : 0x01)) {
+ return (rv);
+ }
+
+ /* Remove all the random bits up to 0x00 (= NULL char) */
+ for (i = 2; (*plen - i) > 0; i++) {
+ if (padbuf[i] == 0x00) {
+ i++;
+ if (i < MIN_PKCS1_PADLEN) {
+ return (rv);
+ }
+ *plen -= i;
+
+ return (0);
+ } else if (method == PKCS1_VERIFY && padbuf[i] != 0xFF) {
+ return (rv);
+ }
+ }
+
+ return (rv);
+}