1/* crypto/modes/wrap128.c */
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 2013 The OpenSSL Project.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 *    software must display the following acknowledgment:
23 *    "This product includes software developed by the OpenSSL Project
24 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 *    endorse or promote products derived from this software without
28 *    prior written permission. For written permission, please contact
29 *    licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 *    nor may "OpenSSL" appear in their names without prior written
33 *    permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 *    acknowledgment:
37 *    "This product includes software developed by the OpenSSL Project
38 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 */
54
55#include "cryptlib.h"
56#include <openssl/modes.h>
57
58static const unsigned char default_iv[] = {
59    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
60};
61
62/*
63 * Input size limit: lower than maximum of standards but far larger than
64 * anything that will be used in practice.
65 */
66#define CRYPTO128_WRAP_MAX (1UL << 31)
67
68size_t CRYPTO_128_wrap(void *key, const unsigned char *iv,
69                       unsigned char *out,
70                       const unsigned char *in, size_t inlen,
71                       block128_f block)
72{
73    unsigned char *A, B[16], *R;
74    size_t i, j, t;
75    if ((inlen & 0x7) || (inlen < 8) || (inlen > CRYPTO128_WRAP_MAX))
76        return 0;
77    A = B;
78    t = 1;
79    memmove(out + 8, in, inlen);
80    if (!iv)
81        iv = default_iv;
82
83    memcpy(A, iv, 8);
84
85    for (j = 0; j < 6; j++) {
86        R = out + 8;
87        for (i = 0; i < inlen; i += 8, t++, R += 8) {
88            memcpy(B + 8, R, 8);
89            block(B, B, key);
90            A[7] ^= (unsigned char)(t & 0xff);
91            if (t > 0xff) {
92                A[6] ^= (unsigned char)((t >> 8) & 0xff);
93                A[5] ^= (unsigned char)((t >> 16) & 0xff);
94                A[4] ^= (unsigned char)((t >> 24) & 0xff);
95            }
96            memcpy(R, B + 8, 8);
97        }
98    }
99    memcpy(out, A, 8);
100    return inlen + 8;
101}
102
103size_t CRYPTO_128_unwrap(void *key, const unsigned char *iv,
104                         unsigned char *out,
105                         const unsigned char *in, size_t inlen,
106                         block128_f block)
107{
108    unsigned char *A, B[16], *R;
109    size_t i, j, t;
110    inlen -= 8;
111    if ((inlen & 0x7) || (inlen < 16) || (inlen > CRYPTO128_WRAP_MAX))
112        return 0;
113    A = B;
114    t = 6 * (inlen >> 3);
115    memcpy(A, in, 8);
116    memmove(out, in + 8, inlen);
117    for (j = 0; j < 6; j++) {
118        R = out + inlen - 8;
119        for (i = 0; i < inlen; i += 8, t--, R -= 8) {
120            A[7] ^= (unsigned char)(t & 0xff);
121            if (t > 0xff) {
122                A[6] ^= (unsigned char)((t >> 8) & 0xff);
123                A[5] ^= (unsigned char)((t >> 16) & 0xff);
124                A[4] ^= (unsigned char)((t >> 24) & 0xff);
125            }
126            memcpy(B + 8, R, 8);
127            block(B, B, key);
128            memcpy(R, B + 8, 8);
129        }
130    }
131    if (!iv)
132        iv = default_iv;
133    if (memcmp(A, iv, 8)) {
134        OPENSSL_cleanse(out, inlen);
135        return 0;
136    }
137    return inlen;
138}
139