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