1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * IDEA low level APIs are deprecated for public use, but still ok for internal
12e1051a39Sopenharmony_ci * use where we're using them to implement the higher level EVP interface, as is
13e1051a39Sopenharmony_ci * the case here.
14e1051a39Sopenharmony_ci */
15e1051a39Sopenharmony_ci#include "internal/deprecated.h"
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include <openssl/idea.h>
18e1051a39Sopenharmony_ci#include "idea_local.h"
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_cistatic IDEA_INT inverse(unsigned int xin);
21e1051a39Sopenharmony_civoid IDEA_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks)
22e1051a39Sopenharmony_ci{
23e1051a39Sopenharmony_ci    int i;
24e1051a39Sopenharmony_ci    register IDEA_INT *kt, *kf, r0, r1, r2;
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_ci    kt = &(ks->data[0][0]);
27e1051a39Sopenharmony_ci    n2s(key, kt[0]);
28e1051a39Sopenharmony_ci    n2s(key, kt[1]);
29e1051a39Sopenharmony_ci    n2s(key, kt[2]);
30e1051a39Sopenharmony_ci    n2s(key, kt[3]);
31e1051a39Sopenharmony_ci    n2s(key, kt[4]);
32e1051a39Sopenharmony_ci    n2s(key, kt[5]);
33e1051a39Sopenharmony_ci    n2s(key, kt[6]);
34e1051a39Sopenharmony_ci    n2s(key, kt[7]);
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    kf = kt;
37e1051a39Sopenharmony_ci    kt += 8;
38e1051a39Sopenharmony_ci    for (i = 0; i < 6; i++) {
39e1051a39Sopenharmony_ci        r2 = kf[1];
40e1051a39Sopenharmony_ci        r1 = kf[2];
41e1051a39Sopenharmony_ci        *(kt++) = ((r2 << 9) | (r1 >> 7)) & 0xffff;
42e1051a39Sopenharmony_ci        r0 = kf[3];
43e1051a39Sopenharmony_ci        *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
44e1051a39Sopenharmony_ci        r1 = kf[4];
45e1051a39Sopenharmony_ci        *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
46e1051a39Sopenharmony_ci        r0 = kf[5];
47e1051a39Sopenharmony_ci        *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
48e1051a39Sopenharmony_ci        r1 = kf[6];
49e1051a39Sopenharmony_ci        *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
50e1051a39Sopenharmony_ci        r0 = kf[7];
51e1051a39Sopenharmony_ci        *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
52e1051a39Sopenharmony_ci        r1 = kf[0];
53e1051a39Sopenharmony_ci        if (i >= 5)
54e1051a39Sopenharmony_ci            break;
55e1051a39Sopenharmony_ci        *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
56e1051a39Sopenharmony_ci        *(kt++) = ((r1 << 9) | (r2 >> 7)) & 0xffff;
57e1051a39Sopenharmony_ci        kf += 8;
58e1051a39Sopenharmony_ci    }
59e1051a39Sopenharmony_ci}
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_civoid IDEA_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk)
62e1051a39Sopenharmony_ci{
63e1051a39Sopenharmony_ci    int r;
64e1051a39Sopenharmony_ci    register IDEA_INT *fp, *tp, t;
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci    tp = &(dk->data[0][0]);
67e1051a39Sopenharmony_ci    fp = &(ek->data[8][0]);
68e1051a39Sopenharmony_ci    for (r = 0; r < 9; r++) {
69e1051a39Sopenharmony_ci        *(tp++) = inverse(fp[0]);
70e1051a39Sopenharmony_ci        *(tp++) = ((int)(0x10000L - fp[2]) & 0xffff);
71e1051a39Sopenharmony_ci        *(tp++) = ((int)(0x10000L - fp[1]) & 0xffff);
72e1051a39Sopenharmony_ci        *(tp++) = inverse(fp[3]);
73e1051a39Sopenharmony_ci        if (r == 8)
74e1051a39Sopenharmony_ci            break;
75e1051a39Sopenharmony_ci        fp -= 6;
76e1051a39Sopenharmony_ci        *(tp++) = fp[4];
77e1051a39Sopenharmony_ci        *(tp++) = fp[5];
78e1051a39Sopenharmony_ci    }
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci    tp = &(dk->data[0][0]);
81e1051a39Sopenharmony_ci    t = tp[1];
82e1051a39Sopenharmony_ci    tp[1] = tp[2];
83e1051a39Sopenharmony_ci    tp[2] = t;
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci    t = tp[49];
86e1051a39Sopenharmony_ci    tp[49] = tp[50];
87e1051a39Sopenharmony_ci    tp[50] = t;
88e1051a39Sopenharmony_ci}
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci/* taken directly from the 'paper' I'll have a look at it later */
91e1051a39Sopenharmony_cistatic IDEA_INT inverse(unsigned int xin)
92e1051a39Sopenharmony_ci{
93e1051a39Sopenharmony_ci    long n1, n2, q, r, b1, b2, t;
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_ci    if (xin == 0)
96e1051a39Sopenharmony_ci        b2 = 0;
97e1051a39Sopenharmony_ci    else {
98e1051a39Sopenharmony_ci        n1 = 0x10001;
99e1051a39Sopenharmony_ci        n2 = xin;
100e1051a39Sopenharmony_ci        b2 = 1;
101e1051a39Sopenharmony_ci        b1 = 0;
102e1051a39Sopenharmony_ci
103e1051a39Sopenharmony_ci        do {
104e1051a39Sopenharmony_ci            r = (n1 % n2);
105e1051a39Sopenharmony_ci            q = (n1 - r) / n2;
106e1051a39Sopenharmony_ci            if (r == 0) {
107e1051a39Sopenharmony_ci                if (b2 < 0)
108e1051a39Sopenharmony_ci                    b2 = 0x10001 + b2;
109e1051a39Sopenharmony_ci            } else {
110e1051a39Sopenharmony_ci                n1 = n2;
111e1051a39Sopenharmony_ci                n2 = r;
112e1051a39Sopenharmony_ci                t = b2;
113e1051a39Sopenharmony_ci                b2 = b1 - q * b2;
114e1051a39Sopenharmony_ci                b1 = t;
115e1051a39Sopenharmony_ci            }
116e1051a39Sopenharmony_ci        } while (r != 0);
117e1051a39Sopenharmony_ci    }
118e1051a39Sopenharmony_ci    return (IDEA_INT)b2;
119e1051a39Sopenharmony_ci}
120