1289848Sjkim/* crypto/modes/wrap128.c */ 2289848Sjkim/* 3289848Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4289848Sjkim * project. 5289848Sjkim */ 6289848Sjkim/* ==================================================================== 7289848Sjkim * Copyright (c) 2013 The OpenSSL Project. All rights reserved. 8289848Sjkim * 9289848Sjkim * Redistribution and use in source and binary forms, with or without 10289848Sjkim * modification, are permitted provided that the following conditions 11289848Sjkim * are met: 12289848Sjkim * 13289848Sjkim * 1. Redistributions of source code must retain the above copyright 14289848Sjkim * notice, this list of conditions and the following disclaimer. 15289848Sjkim * 16289848Sjkim * 2. Redistributions in binary form must reproduce the above copyright 17289848Sjkim * notice, this list of conditions and the following disclaimer in 18289848Sjkim * the documentation and/or other materials provided with the 19289848Sjkim * distribution. 20289848Sjkim * 21289848Sjkim * 3. All advertising materials mentioning features or use of this 22289848Sjkim * software must display the following acknowledgment: 23289848Sjkim * "This product includes software developed by the OpenSSL Project 24289848Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25289848Sjkim * 26289848Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27289848Sjkim * endorse or promote products derived from this software without 28289848Sjkim * prior written permission. For written permission, please contact 29289848Sjkim * licensing@OpenSSL.org. 30289848Sjkim * 31289848Sjkim * 5. Products derived from this software may not be called "OpenSSL" 32289848Sjkim * nor may "OpenSSL" appear in their names without prior written 33289848Sjkim * permission of the OpenSSL Project. 34289848Sjkim * 35289848Sjkim * 6. Redistributions of any form whatsoever must retain the following 36289848Sjkim * acknowledgment: 37289848Sjkim * "This product includes software developed by the OpenSSL Project 38289848Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39289848Sjkim * 40289848Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41289848Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42289848Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43289848Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44289848Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45289848Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46289848Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47289848Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48289848Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49289848Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50289848Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51289848Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 52289848Sjkim * ==================================================================== 53289848Sjkim */ 54289848Sjkim 55289848Sjkim#include "cryptlib.h" 56289848Sjkim#include <openssl/modes.h> 57289848Sjkim 58289848Sjkimstatic const unsigned char default_iv[] = { 59289848Sjkim 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 60289848Sjkim}; 61289848Sjkim 62289848Sjkim/* 63289848Sjkim * Input size limit: lower than maximum of standards but far larger than 64289848Sjkim * anything that will be used in practice. 65289848Sjkim */ 66289848Sjkim#define CRYPTO128_WRAP_MAX (1UL << 31) 67289848Sjkim 68289848Sjkimsize_t CRYPTO_128_wrap(void *key, const unsigned char *iv, 69289848Sjkim unsigned char *out, 70289848Sjkim const unsigned char *in, size_t inlen, 71289848Sjkim block128_f block) 72289848Sjkim{ 73289848Sjkim unsigned char *A, B[16], *R; 74289848Sjkim size_t i, j, t; 75289848Sjkim if ((inlen & 0x7) || (inlen < 8) || (inlen > CRYPTO128_WRAP_MAX)) 76289848Sjkim return 0; 77289848Sjkim A = B; 78289848Sjkim t = 1; 79291719Sjkim memmove(out + 8, in, inlen); 80289848Sjkim if (!iv) 81289848Sjkim iv = default_iv; 82289848Sjkim 83289848Sjkim memcpy(A, iv, 8); 84289848Sjkim 85289848Sjkim for (j = 0; j < 6; j++) { 86289848Sjkim R = out + 8; 87289848Sjkim for (i = 0; i < inlen; i += 8, t++, R += 8) { 88289848Sjkim memcpy(B + 8, R, 8); 89289848Sjkim block(B, B, key); 90289848Sjkim A[7] ^= (unsigned char)(t & 0xff); 91289848Sjkim if (t > 0xff) { 92289848Sjkim A[6] ^= (unsigned char)((t >> 8) & 0xff); 93289848Sjkim A[5] ^= (unsigned char)((t >> 16) & 0xff); 94289848Sjkim A[4] ^= (unsigned char)((t >> 24) & 0xff); 95289848Sjkim } 96289848Sjkim memcpy(R, B + 8, 8); 97289848Sjkim } 98289848Sjkim } 99289848Sjkim memcpy(out, A, 8); 100289848Sjkim return inlen + 8; 101289848Sjkim} 102289848Sjkim 103289848Sjkimsize_t CRYPTO_128_unwrap(void *key, const unsigned char *iv, 104289848Sjkim unsigned char *out, 105289848Sjkim const unsigned char *in, size_t inlen, 106289848Sjkim block128_f block) 107289848Sjkim{ 108289848Sjkim unsigned char *A, B[16], *R; 109289848Sjkim size_t i, j, t; 110289848Sjkim inlen -= 8; 111289848Sjkim if ((inlen & 0x7) || (inlen < 16) || (inlen > CRYPTO128_WRAP_MAX)) 112289848Sjkim return 0; 113289848Sjkim A = B; 114289848Sjkim t = 6 * (inlen >> 3); 115289848Sjkim memcpy(A, in, 8); 116291719Sjkim memmove(out, in + 8, inlen); 117289848Sjkim for (j = 0; j < 6; j++) { 118289848Sjkim R = out + inlen - 8; 119289848Sjkim for (i = 0; i < inlen; i += 8, t--, R -= 8) { 120289848Sjkim A[7] ^= (unsigned char)(t & 0xff); 121289848Sjkim if (t > 0xff) { 122289848Sjkim A[6] ^= (unsigned char)((t >> 8) & 0xff); 123289848Sjkim A[5] ^= (unsigned char)((t >> 16) & 0xff); 124289848Sjkim A[4] ^= (unsigned char)((t >> 24) & 0xff); 125289848Sjkim } 126289848Sjkim memcpy(B + 8, R, 8); 127289848Sjkim block(B, B, key); 128289848Sjkim memcpy(R, B + 8, 8); 129289848Sjkim } 130289848Sjkim } 131289848Sjkim if (!iv) 132289848Sjkim iv = default_iv; 133289848Sjkim if (memcmp(A, iv, 8)) { 134289848Sjkim OPENSSL_cleanse(out, inlen); 135289848Sjkim return 0; 136289848Sjkim } 137289848Sjkim return inlen; 138289848Sjkim} 139