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