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 <inttypes.h>
16#include "internal/deprecated.h"
17
18#include <openssl/idea.h>
19#include "idea_local.h"
20
21static IDEA_INT inverse(unsigned int xin);
22void IDEA_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks)
23{
24    int i;
25    register IDEA_INT *kt, *kf, r0, r1, r2;
26
27    kt = &(ks->data[0][0]);
28    n2s(key, kt[0]);
29    n2s(key, kt[1]);
30    n2s(key, kt[2]);
31    n2s(key, kt[3]);
32    n2s(key, kt[4]);
33    n2s(key, kt[5]);
34    n2s(key, kt[6]);
35    n2s(key, kt[7]);
36
37    kf = kt;
38    kt += 8;
39    for (i = 0; i < 6; i++) {
40        r2 = kf[1];
41        r1 = kf[2];
42        *(kt++) = ((r2 << 9) | (r1 >> 7)) & 0xffff;
43        r0 = kf[3];
44        *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
45        r1 = kf[4];
46        *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
47        r0 = kf[5];
48        *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
49        r1 = kf[6];
50        *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
51        r0 = kf[7];
52        *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
53        r1 = kf[0];
54        if (i >= 5)
55            break;
56        *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
57        *(kt++) = ((r1 << 9) | (r2 >> 7)) & 0xffff;
58        kf += 8;
59    }
60}
61
62void IDEA_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk)
63{
64    int r;
65    register IDEA_INT *fp, *tp, t;
66
67    tp = &(dk->data[0][0]);
68    fp = &(ek->data[8][0]);
69    for (r = 0; r < 9; r++) {
70        *(tp++) = inverse(fp[0]);
71        *(tp++) = ((int)(0x10000L - fp[2]) & 0xffff);
72        *(tp++) = ((int)(0x10000L - fp[1]) & 0xffff);
73        *(tp++) = inverse(fp[3]);
74        if (r == 8)
75            break;
76        fp -= 6;
77        *(tp++) = fp[4];
78        *(tp++) = fp[5];
79    }
80
81    tp = &(dk->data[0][0]);
82    t = tp[1];
83    tp[1] = tp[2];
84    tp[2] = t;
85
86    t = tp[49];
87    tp[49] = tp[50];
88    tp[50] = t;
89}
90
91/* taken directly from the 'paper' I'll have a look at it later */
92static IDEA_INT inverse(unsigned int xin)
93{
94    int32_t n1, n2, q, r, b1, b2, t;
95
96    if (xin == 0)
97        b2 = 0;
98    else {
99        n1 = 0x10001;
100        n2 = xin;
101        b2 = 1;
102        b1 = 0;
103
104        do {
105            r = (n1 % n2);
106            q = (n1 - r) / n2;
107            if (r == 0) {
108                if (b2 < 0)
109                    b2 = 0x10001 + b2;
110            } else {
111                n1 = n2;
112                n2 = r;
113                t = b2;
114                b2 = b1 - q * b2;
115                b1 = t;
116            }
117        } while (r != 0);
118    }
119    return (IDEA_INT)b2;
120}
121