/* * 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 #include "padding.h" #ifdef _KERNEL #include #else #include #include #endif /* * This is padding as decribed in Section 10.3 of RSA PKCS#7. * * The RSA PKCS Padding is in the following format: * +-----------------------------+----+-------------+ * | DATA |0x0k|0x0k|...|0x0k| * +-----------------------------+----+----+---+----+ * where 0x0k is if data_len mod multiple = multiple - k * and multiple < 256 and 1 <= k <= multiple * * If databuf is non NULL, padbuf must be large enough * to contain both databuf and the padding. databuf and * padbuf may be the same buffer. * databuf: * +-----------------------------+ * | DATA | * +-----------------------------+ * datalen * padbuf: * +-----------------------------+----+-------------+ * | DATA |0x0k|0x0k|...|0x0k| * +-----------------------------+----+----+---+----+ * datalen padbuflen * * If databuf is NULL, padbuf only needs to be large * enough for the padding, and datalen must still be * provided to compute the padding value: * padbuf: * +----+-------------+ * |0x0k|0x0k|...|0x0k| * +----+----+---+----+ * datalen padbuflen */ int pkcs7_encode(uint8_t *databuf, size_t datalen, uint8_t *padbuf, size_t padbuflen, uint8_t multiple) { size_t padlen; padlen = multiple - (datalen % multiple); if (databuf == NULL) datalen = 0; if (padlen > padbuflen - datalen) { return (CKR_DATA_LEN_RANGE); } bcopy(databuf, padbuf, datalen); (void) memset(padbuf + datalen, padlen & 0xff, padlen); return (0); } /* * '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. 'padbuf' is unchanged. */ int pkcs7_decode(uint8_t *padbuf, size_t *plen) { int i; size_t padlen; /* Recover the padding value, even if padbuf has trailing nulls */ while (*plen > 0 && (padlen = padbuf[*plen - 1]) == 0) (*plen)--; /* Must have non-zero padding */ if (padlen == 0) return (CKR_ENCRYPTED_DATA_INVALID); /* Count back from all padding bytes; lint tag is for *plen-1-i >= 0 */ /* LINTED E_SUSPICIOUS_COMPARISON */ for (i = 0; i < padlen && (*plen - 1 - i) >= 0; i++) { if (padbuf[*plen - 1 - i] != (padlen & 0xff)) return (CKR_ENCRYPTED_DATA_INVALID); } *plen -= i; return (0); }