Line data Source code
1 : /*
2 : * Copyright (c) 1999 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of KTH nor the names of its contributors may be
18 : * used to endorse or promote products derived from this software without
19 : * specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 : * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 : * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32 :
33 : #include "krb5_locl.h"
34 :
35 : static krb5_error_code
36 25099272 : rr13(unsigned char *buf, size_t len)
37 : {
38 : unsigned char *tmp;
39 25099272 : int bytes = (len + 7) / 8;
40 : int i;
41 25099272 : if(len == 0)
42 0 : return 0;
43 : {
44 25099272 : const int bits = 13 % len;
45 25099272 : const int lbit = len % 8;
46 :
47 25099272 : tmp = malloc(bytes);
48 25099272 : if (tmp == NULL)
49 0 : return ENOMEM;
50 25695376 : memcpy(tmp, buf, bytes);
51 25099272 : if(lbit) {
52 : /* pad final byte with inital bits */
53 0 : tmp[bytes - 1] &= 0xff << (8 - lbit);
54 0 : for(i = lbit; i < 8; i += len)
55 0 : tmp[bytes - 1] |= buf[0] >> i;
56 : }
57 150337328 : for(i = 0; i < bytes; i++) {
58 : int bb;
59 : int b1, s1, b2, s2;
60 : /* calculate first bit position of this byte */
61 125834160 : bb = 8 * i - bits;
62 301866864 : while(bb < 0)
63 50198544 : bb += len;
64 : /* byte offset and shift count */
65 125834160 : b1 = bb / 8;
66 125834160 : s1 = bb % 8;
67 :
68 125834160 : if(bb + 8 > bytes * 8)
69 : /* watch for wraparound */
70 25099272 : s2 = (len + 8 - s1) % 8;
71 : else
72 100734888 : s2 = 8 - s1;
73 125834160 : b2 = (b1 + 1) % bytes;
74 125834160 : buf[i] = (tmp[b1] << s1) | (tmp[b2] >> s2);
75 : }
76 25099272 : free(tmp);
77 : }
78 25099272 : return 0;
79 : }
80 :
81 : /* Add `b' to `a', both being one's complement numbers. */
82 : static void
83 7864635 : add1(unsigned char *a, unsigned char *b, size_t len)
84 : {
85 : int i;
86 7864635 : int carry = 0;
87 133698795 : for(i = len - 1; i >= 0; i--){
88 125834160 : int x = a[i] + b[i] + carry;
89 125834160 : carry = x > 0xff;
90 125834160 : a[i] = x & 0xff;
91 : }
92 8354020 : for(i = len - 1; carry && i >= 0; i--){
93 675993 : int x = a[i] + carry;
94 675993 : carry = x > 0xff;
95 675993 : a[i] = x & 0xff;
96 : }
97 7864635 : }
98 :
99 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
100 1617967 : _krb5_n_fold(const void *str, size_t len, void *key, size_t size)
101 : {
102 : /* if len < size we need at most N * len bytes, ie < 2 * size;
103 : if len > size we need at most 2 * len */
104 1617967 : krb5_error_code ret = 0;
105 1617967 : size_t maxlen = 2 * max(size, len);
106 1617967 : size_t l = 0;
107 1617967 : unsigned char *tmp = malloc(maxlen);
108 1617967 : unsigned char *buf = malloc(len);
109 :
110 1617967 : if (tmp == NULL || buf == NULL) {
111 0 : ret = ENOMEM;
112 0 : goto out;
113 : }
114 :
115 1617967 : memcpy(buf, str, len);
116 1579951 : memset(key, 0, size);
117 : do {
118 25695376 : memcpy(tmp + l, buf, len);
119 25099272 : l += len;
120 25099272 : ret = rr13(buf, len * 8);
121 25099272 : if (ret)
122 0 : goto out;
123 55849108 : while(l >= size) {
124 7864635 : add1(key, tmp, size);
125 7864635 : l -= size;
126 7864635 : if(l == 0)
127 1579951 : break;
128 6246668 : memmove(tmp, tmp + size, l);
129 : }
130 25099272 : } while(l != 0);
131 1617967 : out:
132 1617967 : if (buf) {
133 1617967 : memset(buf, 0, len);
134 1617967 : free(buf);
135 : }
136 1617967 : if (tmp) {
137 1617967 : memset(tmp, 0, maxlen);
138 1617967 : free(tmp);
139 : }
140 1617967 : return ret;
141 : }
|