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