Tcl Library Source Code

Check-in [0b0d3c2be7]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge "mime" and "aes" branches into new "pyk" branch.
Timelines: family | ancestors | descendants | both | pyk | INCOMPATIBLE_LICENSE
Files: files | file ages | folders
SHA3-256: 0b0d3c2be7e04e75d370a0bca3030db29169f3159eea923de5e23e1dc93c49a4
User & Date: pooryorick 2024-11-04 23:42:33
Context
2024-11-04
23:43
Merge [dc82d34ffc]: Bug [f6adf9f137] : correct to-too in error message. Thanks Massimo ! check-in: efce407e9a user: pooryorick tags: pyk, INCOMPATIBLE_LICENSE
23:42
Merge "mime" and "aes" branches into new "pyk" branch. check-in: 0b0d3c2be7 user: pooryorick tags: pyk, INCOMPATIBLE_LICENSE
2024-10-31
12:59
Fix mime failing tests. Add GPL license. Closed-Leaf check-in: f5d6a5e51b user: pooryorick tags: mime, INCOMPATIBLE_LICENSE
2024-09-27
10:44
Merge trunk. check-in: 3242d066e4 user: pooryorick tags: module-aes
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Deleted license_fsul.terms.

Changes to modules/aes/aes.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
















23
24
25
26
27
28
29
30
31
32
33
34
# aes.tcl - 
#
# Copyright (c) 2005 Thorsten Schloermann
# Copyright (c) 2005 Pat Thoyts <[email protected]>
# Copyright (c) 2013 Andreas Kupries
#
# A Tcl implementation of the Advanced Encryption Standard (US FIPS PUB 197)
#
# AES is a block cipher with a block size of 128 bits and a variable
# key size of 128, 192 or 256 bits.
# The algorithm works on each block as a 4x4 state array. There are 4 steps
# in each round:
#   SubBytes    a non-linear substitution step using a predefined S-box
#   ShiftRows   cyclic transposition of rows in the state matrix
#   MixColumns  transformation upon columns in the state matrix
#   AddRoundKey application of round specific sub-key
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------

















package require Tcl 8.5 9

namespace eval ::aes {
    variable uid
    if {![info exists uid]} { set uid 0 }

    namespace export aes

    # constants

    # S-box
    variable sbox {
|
|




<
<
<
<
<
<
<
<
<
<
<





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|







1
2
3
4
5
6











7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# aes.tcl -

# Copyright (c) 2005 Thorsten Schloermann
# Copyright (c) 2005 Pat Thoyts <[email protected]>
# Copyright (c) 2013 Andreas Kupries
#











# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------

# Copyright (c) 2022-2024 Nathan Coulter <[email protected]>
#	ethereum 0x0b5049C148b00a216B29641ab16953b6060Ef8A6
#
# See the file "license_fsul.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# A Tcl implementation of the Advanced Encryption Standard (US FIPS PUB 197)
#
# AES is a block cipher with a block size of 128 bits and a key size of 128,
# 192, or 256 bits.  The algorithm operates on each block as a 4x4 state array.
# There are 4 steps in each round:
#   SubBytes    a non-linear substitution step using a predefined S-box
#   ShiftRows   cyclic transposition of rows in the state matrix
#   MixColumns  transformation upon columns in the state matrix
#   AddRoundKey application of round specific sub-key

package require Tcl 8.5 9

namespace eval ::aes {
    variable uid
    if {![info exists uid]} {set uid 0}

    namespace export aes

    # constants

    # S-box
    variable sbox {
66
67
68
69
70
71
72




























































73
74
75
76
77
78
79
80
81
82
83



84
85










86
87
88
89
90
91
92
93




94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
        0x1f 0xdd 0xa8 0x33 0x88 0x07 0xc7 0x31 0xb1 0x12 0x10 0x59 0x27 0x80 0xec 0x5f
        0x60 0x51 0x7f 0xa9 0x19 0xb5 0x4a 0x0d 0x2d 0xe5 0x7a 0x9f 0x93 0xc9 0x9c 0xef
        0xa0 0xe0 0x3b 0x4d 0xae 0x2a 0xf5 0xb0 0xc8 0xeb 0xbb 0x3c 0x83 0x53 0x99 0x61
        0x17 0x2b 0x04 0x7e 0xba 0x77 0xd6 0x26 0xe1 0x69 0x14 0x63 0x55 0x21 0x0c 0x7d
    }
}





























































# aes::Init --
#
#	Initialise our AES state and calculate the key schedule. An initialization
#	vector is maintained in the state for modes that require one. The key must
#	be binary data of the correct size and the IV must be 16 bytes.
#
#	Nk: columns of the key-array
#	Nr: number of rounds (depends on key-length)
#	Nb: columns of the text-block, is always 4 in AES
#
proc ::aes::Init {mode key iv} {



    switch -exact -- $mode {
        ecb - cbc { }










        cfb - ofb {
            return -code error "$mode mode not implemented"
        }
        default {
            return -code error "invalid mode \"$mode\":\
                must be one of ecb or cbc."
        }
    }





    set size [expr {[string length $key] << 3}]
    switch -exact -- $size {
        128 {set Nk 4; set Nr 10; set Nb 4}
        192 {set Nk 6; set Nr 12; set Nb 4}
        256 {set Nk 8; set Nr 14; set Nb 4}
        default {
            return -code error "invalid key size \"$size\":\
                must be one of 128, 192 or 256."
        }
    }

    variable uid
    set Key [namespace current]::[incr uid]
    upvar #0 $Key state
    if {[binary scan $iv Iu4 state(I)] != 1} {
        return -code error "invalid initialization vector: must be 16 bytes"
    }
    array set state [list M $mode K $key Nk $Nk Nr $Nr Nb $Nb W {}]
    ExpandKey $Key
    return $Key
}

# aes::Reset --
#
#	Reset the initialization vector for the specified key. This permits the
#	key to be reused for encryption or decryption without the expense of
#	re-calculating the key schedule.
#
proc ::aes::Reset {Key iv} {
    upvar #0 $Key state

    if {[binary scan $iv Iu4 state(I)] != 1} {
        return -code error "invalid initialization vector: must be 16 bytes"
    }

    return
}
    
# aes::Final --
#
#	Clean up the key state
#
proc ::aes::Final {Key} {
    # FRINK: nocheck
    unset $Key
}

# -------------------------------------------------------------------------

# 5.1 Cipher:  Encipher a single block of 128 bits.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|









|
>
>
>

|
>
>
>
>
>
>
>
>
>
>








>
>
>
>












<
<
<
<
<
<













>
|
|
|
>


|
|



|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187






188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
        0x1f 0xdd 0xa8 0x33 0x88 0x07 0xc7 0x31 0xb1 0x12 0x10 0x59 0x27 0x80 0xec 0x5f
        0x60 0x51 0x7f 0xa9 0x19 0xb5 0x4a 0x0d 0x2d 0xe5 0x7a 0x9f 0x93 0xc9 0x9c 0xef
        0xa0 0xe0 0x3b 0x4d 0xae 0x2a 0xf5 0xb0 0xc8 0xeb 0xbb 0x3c 0x83 0x53 0x99 0x61
        0x17 0x2b 0x04 0x7e 0xba 0x77 0xd6 0x26 0xe1 0x69 0x14 0x63 0x55 0x21 0x0c 0x7d
    }
}


proc aes::Implementations {} {
	lappend res tcl
	if {[namespace which [namespace current]::EncryptAccelerated] ne {}} {
		lappend res critcl
	}
	return $res
}


proc ::aes::LoadAccelerator {} {
	package require aesc
}


proc aes::KnownImplementations {} {
    return {critcl tcl}
}


proc ::aes::SwitchTo key {
	set saved [namespace export]
	namespace export *
	namespace eval tmp {
		namespace export *
		namespace import [namespace parent]::*
	}
	try {
		if {[namespace which [namespace current]::Decrypt] ne {}} {
			rename [namespace current]::Decrypt {}
		}
		if {[namespace which [namespace current]::Encrypt] ne {}} {
			rename [namespace current]::Encrypt {}
		}

		foreach proc {Decrypt Encrypt Final Init} {
			catch {rename [namespace current]::$proc {}}
		}

		switch $key {
			critcl {
				LoadAccelerator
                rename tmp::DecryptAccelerated Decrypt
                rename tmp::EncryptAccelerated Encrypt
                rename tmp::FinalAccelerated Final
                rename tmp::InitAccelerated Init
			}
			tcl {
                rename tmp::DecryptTcl Decrypt
                rename tmp::EncryptTcl Encrypt
                rename tmp::FinalTcl Final
                rename tmp::InitTcl Init
			}
		}
	} finally {
		namespace delete tmp
		namespace export $saved
	}
}

# aes::InitTcl --
#
#	Initialise our AES state and calculate the key schedule. An initialization
#	vector is maintained in the state for modes that require one. The key must
#	be binary data of the correct size and the IV must be 16 bytes.
#
#	Nk: columns of the key-array
#	Nr: number of rounds (depends on key-length)
#	Nb: columns of the text-block, is always 4 in AES
#
proc ::aes::InitTcl {mode key iv} {
    variable uid
    set Key [namespace current]::[incr uid]
    upvar #0 $Key state
    switch -exact -- $mode {
		cbc {
			if {$iv eq {}} {
				set iv [string repeat \0 16]
			}
		}
        ecb {
			if {$iv ne {}} {
				error [list {In ecb mode an initialization vector is not used.}]
			}
			set iv [string repeat \0 16]
		}
        cfb - ofb {
            return -code error "$mode mode not implemented"
        }
        default {
            return -code error "invalid mode \"$mode\":\
                must be one of ecb or cbc."
        }
    }

	if {[binary scan $iv Iu4 state(I)] != 1} {
		return -code error "invalid initialization vector: must be 16 bytes"
	}

    set size [expr {[string length $key] << 3}]
    switch -exact -- $size {
        128 {set Nk 4; set Nr 10; set Nb 4}
        192 {set Nk 6; set Nr 12; set Nb 4}
        256 {set Nk 8; set Nr 14; set Nb 4}
        default {
            return -code error "invalid key size \"$size\":\
                must be one of 128, 192 or 256."
        }
    }







    array set state [list M $mode K $key Nk $Nk Nr $Nr Nb $Nb W {}]
    ExpandKey $Key
    return $Key
}

# aes::Reset --
#
#	Reset the initialization vector for the specified key. This permits the
#	key to be reused for encryption or decryption without the expense of
#	re-calculating the key schedule.
#
proc ::aes::Reset {Key iv} {
    upvar #0 $Key state
	if {$state(M) eq cbc} {
		if {[binary scan $iv Iu4 state(I)] != 1} {
			return -code error "invalid initialization vector: must be 16 bytes"
		}
	}
    return
}

# aes::FinalTcl --
#
#	Clean up the key state
#
proc ::aes::FinalTcl Key {
    # FRINK: nocheck
    unset $Key
}

# -------------------------------------------------------------------------

# 5.1 Cipher:  Encipher a single block of 128 bits.
179
180
181
182
183
184
185




186
187




188
189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
        return -code error "invalid block size: block must be 16 bytes"
    }
    set iv $data

    set n $state(Nr)
    set data [AddRoundKey $Key $state(Nr) $data]
    for {incr n -1} {$n > 0} {incr n -1} {




        set data [InvMixColumns [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]]
    }




    set data [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]
    
    if {$state(M) eq {cbc}} {
        lassign $data     d0 d1 d2 d3
        lassign $state(I) s0 s1 s2 s3
        set data [list \
                      [expr {($d0 ^ $s0) & 0xffffffff}] \
                      [expr {($d1 ^ $s1) & 0xffffffff}] \
                      [expr {($d2 ^ $s2) & 0xffffffff}] \
                      [expr {($d3 ^ $s3) & 0xffffffff}] ]

    } else {
        # Bug 2993029:
        # The integrated clamping we see above only happens for CBC mode.
        set data [Clamp32 $data]
    }

    set state(I) $iv
    binary format Iu4 $data
}

proc ::aes::Clamp32 {data} {
    # Force all elements into 32bit range.
    lassign $data d0 d1 d2 d3
    list \
        [expr {$d0 & 0xffffffff}] \
        [expr {$d1 & 0xffffffff}] \
        [expr {$d2 & 0xffffffff}] \
        [expr {$d3 & 0xffffffff}]
}

# 5.2: KeyExpansion
proc ::aes::ExpandKey {Key} {
    upvar #0 $Key state
    set Rcon [list 0x00000000 0x01000000 0x02000000 0x04000000 0x08000000 \
                   0x10000000 0x20000000 0x40000000 0x80000000 0x1b000000 \
                   0x36000000 0x6c000000 0xd8000000 0xab000000 0x4d000000]
    # Split the key into Nk big-endian words
    binary scan $state(K) I* W
    set max [expr {$state(Nb) * ($state(Nr) + 1)}]
    set i $state(Nk)
    set h [expr {$i - 1}]
    set j 0
    for {} {$i < $max} {incr i; incr h; incr j} {
        set temp [lindex $W $h]
        if {($i % $state(Nk)) == 0} {
            set sub [SubWord [RotWord $temp]]
            set rc [lindex $Rcon [expr {$i/$state(Nk)}]]
            set temp [expr {$sub ^ $rc}]
        } elseif {$state(Nk) > 6 && ($i % $state(Nk)) == 4} { 
            set temp [SubWord $temp]
        }
        lappend W [expr {[lindex $W $j] ^ $temp}]
    }
    set state(W) $W
}

# 5.2: Key Expansion: Apply S-box to each byte in the 32 bit word
proc ::aes::SubWord {w} {
    variable sbox
    set s3 [lindex $sbox [expr {($w >> 24) & 255}]]
    set s2 [lindex $sbox [expr {($w >> 16) & 255}]]
    set s1 [lindex $sbox [expr {($w >> 8 ) & 255}]]
    set s0 [lindex $sbox [expr { $w        & 255}]]
    return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}]
}

proc ::aes::InvSubWord {w} {
    variable xobs
    set s3 [lindex $xobs [expr {($w >> 24) & 255}]]
    set s2 [lindex $xobs [expr {($w >> 16) & 255}]]
    set s1 [lindex $xobs [expr {($w >> 8 ) & 255}]]
    set s0 [lindex $xobs [expr { $w        & 255}]]
    return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}]
}

# 5.2: Key Expansion: Rotate a 32bit word by 8 bits
proc ::aes::RotWord {w} {
    return [expr {(($w << 8) | (($w >> 24) & 0xff)) & 0xffffffff}]
}

# 5.1.1: SubBytes() Transformation
proc ::aes::SubBytes {words} {
    lassign $words w0 w1 w2 w3
    list [SubWord $w0] [SubWord $w1] [SubWord $w2] [SubWord $w3]
}

# 5.3.2: InvSubBytes() Transformation
proc ::aes::InvSubBytes {words} {
    lassign $words w0 w1 w2 w3
    list [InvSubWord $w0] [InvSubWord $w1] [InvSubWord $w2] [InvSubWord $w3]
}

# 5.1.2: ShiftRows() Transformation
proc ::aes::ShiftRows {words} {
    for {set n0 0} {$n0 < 4} {incr n0} {
        set n1 [expr {($n0 + 1) % 4}]
        set n2 [expr {($n0 + 2) % 4}]
        set n3 [expr {($n0 + 3) % 4}]
        lappend r [expr {(  [lindex $words $n0] & 0xff000000)
                         | ([lindex $words $n1] & 0x00ff0000)
                         | ([lindex $words $n2] & 0x0000ff00)
                         | ([lindex $words $n3] & 0x000000ff)
                     }]
    }
    return $r
}


# 5.3.1: InvShiftRows() Transformation
proc ::aes::InvShiftRows {words} {
    for {set n0 0} {$n0 < 4} {incr n0} {
        set n1 [expr {($n0 + 1) % 4}]
        set n2 [expr {($n0 + 2) % 4}]
        set n3 [expr {($n0 + 3) % 4}]
        lappend r [expr {(  [lindex $words $n0] & 0xff000000)
                         | ([lindex $words $n3] & 0x00ff0000)
                         | ([lindex $words $n2] & 0x0000ff00)
                         | ([lindex $words $n1] & 0x000000ff)
                     }]
    }
    return $r
}

# 5.1.3: MixColumns() Transformation
proc ::aes::MixColumns {words} {
    set r {}
    foreach w $words {
        set r0 [expr {(($w >> 24) & 255)}]
        set r1 [expr {(($w >> 16) & 255)}]
        set r2 [expr {(($w >> 8 ) & 255)}]
        set r3 [expr {( $w        & 255)}]

        set s0 [expr {[GFMult2 $r0] ^ [GFMult3 $r1] ^ $r2 ^ $r3}]
        set s1 [expr {$r0 ^ [GFMult2 $r1] ^ [GFMult3 $r2] ^ $r3}]
        set s2 [expr {$r0 ^ $r1 ^ [GFMult2 $r2] ^ [GFMult3 $r3]}]
        set s3 [expr {[GFMult3 $r0] ^ $r1 ^ $r2 ^ [GFMult2 $r3]}]

        lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}]
    }
    return $r
}

# 5.3.3: InvMixColumns() Transformation
proc ::aes::InvMixColumns {words} {
    set r {}
    foreach w $words {
        set r0 [expr {(($w >> 24) & 255)}]
        set r1 [expr {(($w >> 16) & 255)}]
        set r2 [expr {(($w >> 8 ) & 255)}]
        set r3 [expr {( $w        & 255)}]








>
>
>
>


>
>
>
>

|




|
|
|
|
>






<














|





|










|








|








|









|




|





|





|















|














|


















|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
        return -code error "invalid block size: block must be 16 bytes"
    }
    set iv $data

    set n $state(Nr)
    set data [AddRoundKey $Key $state(Nr) $data]
    for {incr n -1} {$n > 0} {incr n -1} {
        set data1 [InvShiftRows $data]
        set data1  [InvSubBytes $data1]
        set data1 [AddRoundKey $Key $n $data1]
        set data1 [InvMixColumns $data1]
        set data [InvMixColumns [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]]
    }

    set data1 [InvShiftRows $data]
    set data1 [InvSubBytes $data1]
    set data1 [AddRoundKey $Key $n $data1]
    set data [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]

    if {$state(M) eq {cbc}} {
        lassign $data     d0 d1 d2 d3
        lassign $state(I) s0 s1 s2 s3
        set data [list \
            [expr {($d0 ^ $s0) & 0xffffffff}] \
            [expr {($d1 ^ $s1) & 0xffffffff}] \
            [expr {($d2 ^ $s2) & 0xffffffff}] \
            [expr {($d3 ^ $s3) & 0xffffffff}] ]
		set state(I) $iv
    } else {
        # Bug 2993029:
        # The integrated clamping we see above only happens for CBC mode.
        set data [Clamp32 $data]
    }


    binary format Iu4 $data
}

proc ::aes::Clamp32 {data} {
    # Force all elements into 32bit range.
    lassign $data d0 d1 d2 d3
    list \
        [expr {$d0 & 0xffffffff}] \
        [expr {$d1 & 0xffffffff}] \
        [expr {$d2 & 0xffffffff}] \
        [expr {$d3 & 0xffffffff}]
}

# 5.2: KeyExpansion
proc ::aes::ExpandKey Key {
    upvar #0 $Key state
    set Rcon [list 0x00000000 0x01000000 0x02000000 0x04000000 0x08000000 \
                   0x10000000 0x20000000 0x40000000 0x80000000 0x1b000000 \
                   0x36000000 0x6c000000 0xd8000000 0xab000000 0x4d000000]
    # Split the key into Nk big-endian words
    binary scan $state(K) Iu* W
    set max [expr {$state(Nb) * ($state(Nr) + 1)}]
    set i $state(Nk)
    set h [expr {$i - 1}]
    set j 0
    for {} {$i < $max} {incr i; incr h; incr j} {
        set temp [lindex $W $h]
        if {($i % $state(Nk)) == 0} {
            set sub [SubWord [RotWord $temp]]
            set rc [lindex $Rcon [expr {$i/$state(Nk)}]]
            set temp [expr {$sub ^ $rc}]
        } elseif {$state(Nk) > 6 && ($i % $state(Nk)) == 4} {
            set temp [SubWord $temp]
        }
        lappend W [expr {[lindex $W $j] ^ $temp}]
    }
    set state(W) $W
}

# 5.2: Key Expansion: Apply S-box to each byte in the 32 bit word
proc ::aes::SubWord w {
    variable sbox
    set s3 [lindex $sbox [expr {($w >> 24) & 255}]]
    set s2 [lindex $sbox [expr {($w >> 16) & 255}]]
    set s1 [lindex $sbox [expr {($w >> 8 ) & 255}]]
    set s0 [lindex $sbox [expr { $w        & 255}]]
    return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}]
}

proc ::aes::InvSubWord w {
    variable xobs
    set s3 [lindex $xobs [expr {($w >> 24) & 255}]]
    set s2 [lindex $xobs [expr {($w >> 16) & 255}]]
    set s1 [lindex $xobs [expr {($w >> 8 ) & 255}]]
    set s0 [lindex $xobs [expr { $w        & 255}]]
    return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}]
}

# 5.2: Key Expansion: Rotate a 32bit word by 8 bits
proc ::aes::RotWord w {
    return [expr {(($w << 8) | (($w >> 24) & 0xff)) & 0xffffffff}]
}

# 5.1.1: SubBytes() Transformation
proc ::aes::SubBytes words {
    lassign $words w0 w1 w2 w3
    list [SubWord $w0] [SubWord $w1] [SubWord $w2] [SubWord $w3]
}

# 5.3.2: InvSubBytes() Transformation
proc ::aes::InvSubBytes words {
    lassign $words w0 w1 w2 w3
    list [InvSubWord $w0] [InvSubWord $w1] [InvSubWord $w2] [InvSubWord $w3]
}

# 5.1.2: ShiftRows() Transformation
proc ::aes::ShiftRows words {
    for {set n0 0} {$n0 < 4} {incr n0} {
        set n1 [expr {($n0 + 1) % 4}]
        set n2 [expr {($n0 + 2) % 4}]
        set n3 [expr {($n0 + 3) % 4}]
        lappend r [expr {(  [lindex $words $n0] & 0xff000000)
                         | ([lindex $words $n1] & 0x00ff0000)
                         | ([lindex $words $n2] & 0x0000ff00)
                         | ([lindex $words $n3] & 0x000000ff)
                     }]
    }
    return $r
}


# 5.3.1: InvShiftRows() Transformation
proc ::aes::InvShiftRows words {
    for {set n0 0} {$n0 < 4} {incr n0} {
        set n1 [expr {($n0 + 1) % 4}]
        set n2 [expr {($n0 + 2) % 4}]
        set n3 [expr {($n0 + 3) % 4}]
        lappend r [expr {(  [lindex $words $n0] & 0xff000000)
                         | ([lindex $words $n3] & 0x00ff0000)
                         | ([lindex $words $n2] & 0x0000ff00)
                         | ([lindex $words $n1] & 0x000000ff)
                     }]
    }
    return $r
}

# 5.1.3: MixColumns() Transformation
proc ::aes::MixColumns words {
    set r {}
    foreach w $words {
        set r0 [expr {(($w >> 24) & 255)}]
        set r1 [expr {(($w >> 16) & 255)}]
        set r2 [expr {(($w >> 8 ) & 255)}]
        set r3 [expr {( $w        & 255)}]

        set s0 [expr {[GFMult2 $r0] ^ [GFMult3 $r1] ^ $r2 ^ $r3}]
        set s1 [expr {$r0 ^ [GFMult2 $r1] ^ [GFMult3 $r2] ^ $r3}]
        set s2 [expr {$r0 ^ $r1 ^ [GFMult2 $r2] ^ [GFMult3 $r3]}]
        set s3 [expr {[GFMult3 $r0] ^ $r1 ^ $r2 ^ [GFMult2 $r3]}]

        lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}]
    }
    return $r
}

# 5.3.3: InvMixColumns() Transformation
proc ::aes::InvMixColumns words {
    set r {}
    foreach w $words {
        set r0 [expr {(($w >> 24) & 255)}]
        set r1 [expr {(($w >> 16) & 255)}]
        set r2 [expr {(($w >> 8 ) & 255)}]
        set r3 [expr {( $w        & 255)}]

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
    set n [expr {$round * $state(Nb)}]
    foreach w $words {
        lappend r [expr {$w ^ [lindex $state(W) $n]}]
        incr n
    }
    return $r
}
    
# -------------------------------------------------------------------------
# ::aes::GFMult*
#
#	some needed functions for multiplication in a Galois-field
#
proc ::aes::GFMult2 {number} {
    # this is a tabular representation of xtime (multiplication by 2)
    # it is used instead of calculation to prevent timing attacks
    set xtime {
        0x00 0x02 0x04 0x06 0x08 0x0a 0x0c 0x0e 0x10 0x12 0x14 0x16 0x18 0x1a 0x1c 0x1e
        0x20 0x22 0x24 0x26 0x28 0x2a 0x2c 0x2e 0x30 0x32 0x34 0x36 0x38 0x3a 0x3c 0x3e 
        0x40 0x42 0x44 0x46 0x48 0x4a 0x4c 0x4e 0x50 0x52 0x54 0x56 0x58 0x5a 0x5c 0x5e
        0x60 0x62 0x64 0x66 0x68 0x6a 0x6c 0x6e 0x70 0x72 0x74 0x76 0x78 0x7a 0x7c 0x7e 
        0x80 0x82 0x84 0x86 0x88 0x8a 0x8c 0x8e 0x90 0x92 0x94 0x96 0x98 0x9a 0x9c 0x9e 
        0xa0 0xa2 0xa4 0xa6 0xa8 0xaa 0xac 0xae 0xb0 0xb2 0xb4 0xb6 0xb8 0xba 0xbc 0xbe 
        0xc0 0xc2 0xc4 0xc6 0xc8 0xca 0xcc 0xce 0xd0 0xd2 0xd4 0xd6 0xd8 0xda 0xdc 0xde 
        0xe0 0xe2 0xe4 0xe6 0xe8 0xea 0xec 0xee 0xf0 0xf2 0xf4 0xf6 0xf8 0xfa 0xfc 0xfe 
        0x1b 0x19 0x1f 0x1d 0x13 0x11 0x17 0x15 0x0b 0x09 0x0f 0x0d 0x03 0x01 0x07 0x05 
        0x3b 0x39 0x3f 0x3d 0x33 0x31 0x37 0x35 0x2b 0x29 0x2f 0x2d 0x23 0x21 0x27 0x25 
        0x5b 0x59 0x5f 0x5d 0x53 0x51 0x57 0x55 0x4b 0x49 0x4f 0x4d 0x43 0x41 0x47 0x45 
        0x7b 0x79 0x7f 0x7d 0x73 0x71 0x77 0x75 0x6b 0x69 0x6f 0x6d 0x63 0x61 0x67 0x65 
        0x9b 0x99 0x9f 0x9d 0x93 0x91 0x97 0x95 0x8b 0x89 0x8f 0x8d 0x83 0x81 0x87 0x85 
        0xbb 0xb9 0xbf 0xbd 0xb3 0xb1 0xb7 0xb5 0xab 0xa9 0xaf 0xad 0xa3 0xa1 0xa7 0xa5 
        0xdb 0xd9 0xdf 0xdd 0xd3 0xd1 0xd7 0xd5 0xcb 0xc9 0xcf 0xcd 0xc3 0xc1 0xc7 0xc5 
        0xfb 0xf9 0xff 0xfd 0xf3 0xf1 0xf7 0xf5 0xeb 0xe9 0xef 0xed 0xe3 0xe1 0xe7 0xe5
    }
    lindex $xtime $number
}

proc ::aes::GFMult3 {number} {
    # multliply by 2 (via GFMult2) and add the number again on the result (via XOR)
    expr {$number ^ [GFMult2 $number]}
}

proc ::aes::GFMult09 {number} {
    # 09 is: (02*02*02) + 01
    expr {[GFMult2 [GFMult2 [GFMult2 $number]]] ^ $number}
}

proc ::aes::GFMult0b {number} {
    # 0b is: (02*02*02) + 02 + 01
    #return [expr [GFMult2 [GFMult2 [GFMult2 $number]]] ^ [GFMult2 $number] ^ $number]
    #set g0 [GFMult2 $number]
    expr {[GFMult09 $number] ^ [GFMult2 $number]}
}

proc ::aes::GFMult0d {number} {
    # 0d is: (02*02*02) + (02*02) + 01
    set temp [GFMult2 [GFMult2 $number]]
    expr {[GFMult2 $temp] ^ ($temp ^ $number)}
}

proc ::aes::GFMult0e {number} {
    # 0e is: (02*02*02) + (02*02) + 02
    set temp [GFMult2 [GFMult2 $number]]
    expr {[GFMult2 $temp] ^ ($temp ^ [GFMult2 $number])}
}

# -------------------------------------------------------------------------

# aes::Encrypt --
#
#	Encrypt a blocks of plain text and returns blocks of cipher text.
#	The input data must be a multiple of the block size (16).
#
proc ::aes::Encrypt {Key data} {
    set len [string length $data]
    if {($len % 16) != 0} {
        return -code error "invalid block size: AES requires 16 byte blocks"
    }

    set result {}
    for {set i 0} {$i < $len} {incr i 1} {
        set block [string range $data $i [incr i 15]]
        append result [EncryptBlock $Key $block]
    }
    return $result
}

# aes::Decrypt --
#
#	Decrypt blocks of cipher text and returns blocks of plain text.
#	The input data must be a multiple of the block size (16).
#
proc ::aes::Decrypt {Key data} {
    set len [string length $data]
    if {($len % 16) != 0} {
        return -code error "invalid block size: AES requires 16 byte blocks"
    }

    set result {}
    for {set i 0} {$i < $len} {incr i 1} {
        set block [string range $data $i [incr i 15]]
        append result [DecryptBlock $Key $block]
    }
    return $result
}

# -------------------------------------------------------------------------
# chan event handler for chunked file reading.
#
proc ::aes::Chunk {Key in {out {}} {chunksize 4096}} {
    upvar #0 $Key state

    #puts ||CHUNK.X||i=$in|o=$out|c=$chunksize|eof=[eof $in]
    
    if {[eof $in]} {
        chan event $in readable {}
        set state(reading) 0
    }

    set data [read $in $chunksize]

    #puts ||CHUNK.R||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data||

    # Do nothing when data was read at all.
    if {$data eq {}} return

    if {[eof $in]} {
        #puts CHUNK.Z
        set data [Pad $data 16]
    }

    #puts ||CHUNK.P||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data||
    
    if {$out eq {}} {
        append state(output) [$state(cmd) $Key $data]
    } else {
        puts -nonewline $out [$state(cmd) $Key $data]
    }
}

proc ::aes::SetOneOf {lst item} {
    set ndx [lsearch -glob $lst "${item}*"]
    if {$ndx == -1} {
        set err [join $lst ", "]







|





|




|

|
|
|
|
|
|
|
|
|
|
|
|





|




|




|






|





|












|


















|
















|
<
|

|


|















|

|

|







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
    set n [expr {$round * $state(Nb)}]
    foreach w $words {
        lappend r [expr {$w ^ [lindex $state(W) $n]}]
        incr n
    }
    return $r
}

# -------------------------------------------------------------------------
# ::aes::GFMult*
#
#	some needed functions for multiplication in a Galois-field
#
proc ::aes::GFMult2 number {
    # this is a tabular representation of xtime (multiplication by 2)
    # it is used instead of calculation to prevent timing attacks
    set xtime {
        0x00 0x02 0x04 0x06 0x08 0x0a 0x0c 0x0e 0x10 0x12 0x14 0x16 0x18 0x1a 0x1c 0x1e
        0x20 0x22 0x24 0x26 0x28 0x2a 0x2c 0x2e 0x30 0x32 0x34 0x36 0x38 0x3a 0x3c 0x3e
        0x40 0x42 0x44 0x46 0x48 0x4a 0x4c 0x4e 0x50 0x52 0x54 0x56 0x58 0x5a 0x5c 0x5e
        0x60 0x62 0x64 0x66 0x68 0x6a 0x6c 0x6e 0x70 0x72 0x74 0x76 0x78 0x7a 0x7c 0x7e
        0x80 0x82 0x84 0x86 0x88 0x8a 0x8c 0x8e 0x90 0x92 0x94 0x96 0x98 0x9a 0x9c 0x9e
        0xa0 0xa2 0xa4 0xa6 0xa8 0xaa 0xac 0xae 0xb0 0xb2 0xb4 0xb6 0xb8 0xba 0xbc 0xbe
        0xc0 0xc2 0xc4 0xc6 0xc8 0xca 0xcc 0xce 0xd0 0xd2 0xd4 0xd6 0xd8 0xda 0xdc 0xde
        0xe0 0xe2 0xe4 0xe6 0xe8 0xea 0xec 0xee 0xf0 0xf2 0xf4 0xf6 0xf8 0xfa 0xfc 0xfe
        0x1b 0x19 0x1f 0x1d 0x13 0x11 0x17 0x15 0x0b 0x09 0x0f 0x0d 0x03 0x01 0x07 0x05
        0x3b 0x39 0x3f 0x3d 0x33 0x31 0x37 0x35 0x2b 0x29 0x2f 0x2d 0x23 0x21 0x27 0x25
        0x5b 0x59 0x5f 0x5d 0x53 0x51 0x57 0x55 0x4b 0x49 0x4f 0x4d 0x43 0x41 0x47 0x45
        0x7b 0x79 0x7f 0x7d 0x73 0x71 0x77 0x75 0x6b 0x69 0x6f 0x6d 0x63 0x61 0x67 0x65
        0x9b 0x99 0x9f 0x9d 0x93 0x91 0x97 0x95 0x8b 0x89 0x8f 0x8d 0x83 0x81 0x87 0x85
        0xbb 0xb9 0xbf 0xbd 0xb3 0xb1 0xb7 0xb5 0xab 0xa9 0xaf 0xad 0xa3 0xa1 0xa7 0xa5
        0xdb 0xd9 0xdf 0xdd 0xd3 0xd1 0xd7 0xd5 0xcb 0xc9 0xcf 0xcd 0xc3 0xc1 0xc7 0xc5
        0xfb 0xf9 0xff 0xfd 0xf3 0xf1 0xf7 0xf5 0xeb 0xe9 0xef 0xed 0xe3 0xe1 0xe7 0xe5
    }
    lindex $xtime $number
}

proc ::aes::GFMult3 number {
    # multliply by 2 (via GFMult2) and add the number again on the result (via XOR)
    expr {$number ^ [GFMult2 $number]}
}

proc ::aes::GFMult09 number {
    # 09 is: (02*02*02) + 01
    expr {[GFMult2 [GFMult2 [GFMult2 $number]]] ^ $number}
}

proc ::aes::GFMult0b number {
    # 0b is: (02*02*02) + 02 + 01
    #return [expr [GFMult2 [GFMult2 [GFMult2 $number]]] ^ [GFMult2 $number] ^ $number]
    #set g0 [GFMult2 $number]
    expr {[GFMult09 $number] ^ [GFMult2 $number]}
}

proc ::aes::GFMult0d number {
    # 0d is: (02*02*02) + (02*02) + 01
    set temp [GFMult2 [GFMult2 $number]]
    expr {[GFMult2 $temp] ^ ($temp ^ $number)}
}

proc ::aes::GFMult0e number {
    # 0e is: (02*02*02) + (02*02) + 02
    set temp [GFMult2 [GFMult2 $number]]
    expr {[GFMult2 $temp] ^ ($temp ^ [GFMult2 $number])}
}

# -------------------------------------------------------------------------

# aes::Encrypt --
#
#	Encrypt a blocks of plain text and returns blocks of cipher text.
#	The input data must be a multiple of the block size (16).
#
proc ::aes::EncryptTcl {Key data} {
    set len [string length $data]
    if {($len % 16) != 0} {
        return -code error "invalid block size: AES requires 16 byte blocks"
    }

    set result {}
    for {set i 0} {$i < $len} {incr i 1} {
        set block [string range $data $i [incr i 15]]
        append result [EncryptBlock $Key $block]
    }
    return $result
}

# aes::Decrypt --
#
#	Decrypt blocks of cipher text and returns blocks of plain text.
#	The input data must be a multiple of the block size (16).
#
proc ::aes::DecryptTcl {Key data} {
    set len [string length $data]
    if {($len % 16) != 0} {
        return -code error "invalid block size: AES requires 16 byte blocks"
    }

    set result {}
    for {set i 0} {$i < $len} {incr i 1} {
        set block [string range $data $i [incr i 15]]
        append result [DecryptBlock $Key $block]
    }
    return $result
}

# -------------------------------------------------------------------------
# chan event handler for chunked file reading.
#
proc ::aes::Chunk {

	Key in {out {}} {chunksize 4096} chanreading outputvar cmd} {
    #puts ||CHUNK.X||i=$in|o=$out|c=$chunksize|eof=[eof $in]

    if {[eof $in]} {
        chan event $in readable {}
        set $chanreading 0
    }

    set data [read $in $chunksize]

    #puts ||CHUNK.R||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data||

    # Do nothing when data was read at all.
    if {$data eq {}} return

    if {[eof $in]} {
        #puts CHUNK.Z
        set data [Pad $data 16]
    }

    #puts ||CHUNK.P||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data||

    if {$out eq {}} {
        append $outputvar [$cmd $Key $data]
    } else {
        puts -nonewline $out [$cmd $Key $data]
    }
}

proc ::aes::SetOneOf {lst item} {
    set ndx [lsearch -glob $lst "${item}*"]
    if {$ndx == -1} {
        set err [join $lst ", "]
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
    }
    return $data
}

proc ::aes::Pop {varname {nth 0}} {
    upvar 1 $varname args
    set r [lindex $args $nth]
    set args [lreplace $args $nth $nth]
    return $r
}

proc ::aes::aes {args} {
    array set opts {-dir encrypt -mode cbc -key {} -in {} -out {} -chunksize 4096 -hex 0}
    set opts(-iv) [string repeat \0 16]
    set modes {ecb cbc}

    set dirs {encrypt decrypt}
    while {([llength $args] > 1) && [string match -* [set option [lindex $args 0]]]} {
        switch -exact -- $option {
            -mode      { set opts(-mode) [SetOneOf $modes [Pop args 1]] }
            -dir       { set opts(-dir) [SetOneOf $dirs [Pop args 1]] }
            -iv        { set opts(-iv) [CheckSize -iv 16 [Pop args 1]] }
            -key       { set opts(-key) [Pop args 1] }







|



|

<

>







601
602
603
604
605
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
621
622
    }
    return $data
}

proc ::aes::Pop {varname {nth 0}} {
    upvar 1 $varname args
    set r [lindex $args $nth]
    set args [lreplace $args[set args {}] $nth $nth]
    return $r
}

proc ::aes::aes args {
    array set opts {-dir encrypt -mode cbc -key {} -in {} -out {} -chunksize 4096 -hex 0}

    set modes {ecb cbc}
	set opts(-iv) {}
    set dirs {encrypt decrypt}
    while {([llength $args] > 1) && [string match -* [set option [lindex $args 0]]]} {
        switch -exact -- $option {
            -mode      { set opts(-mode) [SetOneOf $modes [Pop args 1]] }
            -dir       { set opts(-dir) [SetOneOf $dirs [Pop args 1]] }
            -iv        { set opts(-iv) [CheckSize -iv 16 [Pop args 1]] }
            -key       { set opts(-key) [Pop args 1] }
580
581
582
583
584
585
586
587



588
589
590



591



592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607



608
609
610
611
612
613
614
615



616
617
618
619
620
621
622
623
624
625
        if {[llength $args] != 0} {
            return -code error "wrong \# args:\
                should be \"aes ?options...? -key keydata -in channel\""
        }

        set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]

        set readcmd [list [namespace origin Chunk] \



                         $Key $opts(-in) $opts(-out) \
                         $opts(-chunksize)]




        upvar 1 $Key state



        set state(reading) 1
        if {[string equal $opts(-dir) "encrypt"]} {
            set state(cmd) Encrypt
        } else {
            set state(cmd) Decrypt
        }
        set state(output) ""
        chan event $opts(-in) readable $readcmd
        if {[info commands ::tkwait] != {}} {
            tkwait variable [subst $Key](reading)
        } else {
            vwait [subst $Key](reading)
        }
        if {$opts(-out) == {}} {
            set r $state(output)
        }



        Final $Key
    }

    if {$opts(-hex)} {
        binary scan $r H* r
    }
    return $r
}




# -------------------------------------------------------------------------

package provide aes 1.2.2

# -------------------------------------------------------------------------
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:







|
>
>
>
|
|

>
>
>
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>








>
>
>



|






665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
        if {[llength $args] != 0} {
            return -code error "wrong \# args:\
                should be \"aes ?options...? -key keydata -in channel\""
        }

        set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]

        set readcmd [list ::apply [list {
			Key in out chunksize readingvar outputvar readcmd
		} {
			Chunk $Key $in $out $chunksize $readingvar $outputvar $readcmd
		} [namespace current]] $Key $opts(-in) $opts(-out) $opts(-chunksize)]


		set chanstatens [namespace eval [info cmdcount]_chan {
			namespace current
		}]
		try {
			set chanreading ${chanstatens}::reading
			set chanoutput ${chanstatens}::output
			lappend readcmd $chanreading $chanoutput
			set $chanreading 1
			if {[string equal $opts(-dir) encrypt]} {
				lappend readcmd Encrypt
			} else {
				lappend readcmd Decrypt
			}
			set state(output) {} 
			chan event $opts(-in) readable $readcmd
			if {[info commands ::tkwait] ne {}} {
				tkwait variable $chanreading
			} else {
				vwait $chanreading 
			}
			if {$opts(-out) eq {}} {
				set r [set $chanoutput]
			}
		} finally {
			namespace delete $chanstatens
		}
        Final $Key
    }

    if {$opts(-hex)} {
        binary scan $r H* r
    }
    return $r
}

# 0 by default because use of the accelerated routines incurs fees.
aes::SwitchTo tcl

# -------------------------------------------------------------------------

package provide aes 1.2.3

# -------------------------------------------------------------------------
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

Changes to modules/aes/aes.test.

1
2










3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26










27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351








352
353
354
355
356
357
358
# aes.test - Copyright (c) 2005 Thorsten Schloermann
#










# the test-values are taken from:
#     http://csrc.nist.gov/CryptoToolkit/aes/rijndael/rijndael-vals.zip
#     where only the first 12 entries of Know Answer Test for variable key and
#     variable text are used
#     Unfortunately, only encryption is tested by this.
#
#
# Monte Carlo Tests with 4 Million cycles through the algorithm will need too much time
#
# $Id: aes.test,v 1.8 2010/07/06 19:39:00 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2

testing {
    useLocal aes.tcl aes

}











# -------------------------------------------------------------------------

# data for variable key KAT

# Sample vectors from FIPS 197 specification document.
#
test aes-fips-C.1e {Test vector for AES-128 from FIPS-197 Appendix C.1} -setup {
    set txt [binary format H* 00112233445566778899aabbccddeeff]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
} -body {
    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 69c4e0d86a7b0430d8cdb78070b4c55a

test aes-fips-C.1d {Test vector for AES-128 from FIPS-197 Appendix C.1} -setup {
    set txt [binary format H* 69c4e0d86a7b0430d8cdb78070b4c55a]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
} -body {
    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 00112233445566778899aabbccddeeff

test aes-fips-C.2e {Test vector for AES-192 from FIPS-197 Appendix C.2} -setup {
    set txt [binary format H* 00112233445566778899aabbccddeeff]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f1011121314151617]
} -body {
    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result dda97ca4864cdfe06eaf70a0ec0d7191

test aes-fips-C.2d {Test vector for AES-192 from FIPS-197 Appendix C.2} -setup {
    set txt [binary format H* dda97ca4864cdfe06eaf70a0ec0d7191]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f1011121314151617]
} -body {
    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 00112233445566778899aabbccddeeff

test aes-fips-C.3e {Test vector for AES-256 from FIPS-197 Appendix C.3} -setup {
    set txt [binary format H* 00112233445566778899aabbccddeeff]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f]
} -body {
    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 8ea2b7ca516745bfeafc49904b496089

test aes-fips-C.3d {Test vector for AES-256 from FIPS-197 Appendix C.3} -setup {
    set txt [binary format H* 8ea2b7ca516745bfeafc49904b496089]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f]
} -body {
    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 00112233445566778899aabbccddeeff

test aes-kat-ecb-128e {Known answer tests - AES-128 ECB encryption} -setup {
    set txt [binary format H* 000102030405060708090a0b0c0d0e0f]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
} -body {
    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 0a940bb5416ef045f1c39458c653ea5a

test aes-kat-ecb-128d {Known answer tests - AES-128 ECB decryption} -setup {
    set txt [binary format H* 0a940bb5416ef045f1c39458c653ea5a]
    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
} -body {
    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 000102030405060708090a0b0c0d0e0f

test aes-kat-ecb-192e {Known answer tests - AES-192 ECB encryption} -setup {
    set txt [binary format H* 000102030405060708090a0b0c0d0e0f]
    set key [binary format H* 000102030405060708090A0B0C0D0E0F1011121314151617]
} -body {
    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 0060bffe46834bb8da5cf9a61ff220ae

test aes-kat-ecb-192d {Known answer tests - AES-192 ECB decryption} -setup {
    set txt [binary format H* 0060bffe46834bb8da5cf9a61ff220ae]
    set key [binary format H* 000102030405060708090A0B0C0D0E0F1011121314151617]
} -body {
    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 000102030405060708090a0b0c0d0e0f

test aes-kat-ecb-256e {Known answer tests - AES-256 ECB encryption} -setup {
    set txt [binary format H* 000102030405060708090a0b0c0d0e0f]
    set key [binary format H* 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F]
} -body {
    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 5a6e045708fb7196f02e553d02c3a692

test aes-kat-ecb-256d {Known answer tests - AES-256 ECB decryption} -setup {
    set txt [binary format H* 5a6e045708fb7196f02e553d02c3a692]
    set key [binary format H* 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F]
} -body {
    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
    binary scan $enc H* r
    set r
} -cleanup {
    unset txt key enc r
} -result 000102030405060708090a0b0c0d0e0f


# N key ic plain cipher
set vectors {
    1 06a9214036b8a15b512e03d534120006 3dafba429d9eb430b422da802c9fac41
      53696e676c6520626c6f636b206d7367 e353779c1079aeb82708942dbe77181a
    2 c286696d887c9aa0611bbb3e2025a45a 562e17996d093d28ddb3ba695a2e6f58
      000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
      d296cd94c2cccf8a3a863028b5e1dc0a7586602d253cfff91b8266bea6d61ab1
    3 6c3ea0477630ce21a2ce334aa746c2cd c782dc4c098c66cbd9cd27d825682c81
      5468697320697320612034382d62797465206d657373616765202865786163746c7920332041455320626c6f636b7329
      d0a02b3836451753d493665d33f0e8862dea54cdb293abc7506939276772f8d5021c19216bad525c8579695d83ba2684    
    4 56e47a38c5598974bc46903dba290349 8ce82eefbea0da3c44699ed7db51b7d9
      a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf
      c30e32ffedc0774e6aff6af0869f71aa0f3af07a9a31a9c684db207eb0ef8e4e35907aa632c3ffdf868bb7b29d3d46ad83ce9f9a102ee99d49a53e87f4c3da55
}

foreach {n key iv pt ct} $vectors {
    test aes-cbc-${n}e {RFC3602 AES-128 CBC mode encryption} -setup {
        set K [binary format H* $key]
        set I [binary format H* $iv]
    } -body {
        set aes [aes::aes -mode cbc -dir enc -key $K -iv $I [binary format H* $pt]]
        binary scan $aes H* r
        set r
    } -cleanup {
        unset r K I aes
    } -result $ct
    
    test aes-cbc-${n}d {RFC3602 AES-128 CBC mode decryption} -setup {
        set K [binary format H* $key]
        set I [binary format H* $iv]
    } -body {
        set aes [aes::aes -mode cbc -dir dec -key $K -iv $I [binary format H* $ct]]
        binary scan $aes H* r
        set r
    } -cleanup {
        unset r K I aes
    } -result $pt
}

# Known answer tests (CBC)
#    0 00000000000000000000000000000000 00000000000000000000000000000000 
#      00000000000000000000000000000000 8a05fc5e095af4848a08d328d3688e3d
#    1 8a05fc5e095af4848a08d328d3688e3d 8a05fc5e095af4848a08d328d3688e3d
#      204f17e2444381f6114ff53934c0bcd3 192d9b3aa10bb2f7846ccba0085c657a
#    2 93286764a85146730e641888db34eb47 192d9b3aa10bb2f7846ccba0085c657a
#      983bf6f5a6dfbcdaa19370666e83a99a 40d8daf6d1fda0a073b3bd18b7695d2e
#    3 d3f0bd9279ace6d37dd7a5906c5db669 40d8daf6d1fda0a073b3bd18b7695d2e
#      c48cd503a21c8ad0b2483ef15f79571d 3edbe80d69a1d2248ca55fc17c4ef3c5

# Bugs

# N key ic plain cipher
set vectors {
    1
    3132333435363738393031323334353637383930313233343536373839303132
    c3f0929f353c2fc78b9c6705397f22c8
    005a0000003b00000000000000000000
    97d94ab5d6a6bf3e9a126b67b8b3bc12
}

foreach {n key iv pt ct} $vectors {
    test aes-cbc-x${n}e {RFC3602 AES-128 CBC mode encryption} -setup {
        set K [binary format H* $key]
        set I [binary format H* $iv]
    } -body {
        set aes [aes::aes -mode cbc -dir enc -key $K -iv $I [binary format H* $pt]]
        binary scan $aes H* r
        set r
    } -cleanup {
        unset r K I aes
    } -result $ct
    
    test aes-cbc-x${n}d {RFC3602 AES-128 CBC mode decryption} -setup {
        set K [binary format H* $key]
        set I [binary format H* $iv]
    } -body {
        set aes [aes::aes -mode cbc -dir dec -key $K -iv $I [binary format H* $ct]]
        binary scan $aes H* r
        set r
    } -cleanup {
        unset r K I aes
    } -result $pt
}

test aes-sf2993029 {aes decrypt, wide integer, sf bug 2993029} -body {
    aes::aes -hex -mode ecb -dir decrypt \
        -key [binary format H* FEDCBA98FEDCBA98FEDCBA98FEDCBA98] \
        [binary format H* 2a666624a86d4c29de37b520781c1069]
} -result 01000000000000003d5afbb584a29f57

# -------------------------------------------------------------------------

test aes-sf-3574004-a {aes use with data starting with a dash, auto-stop} -body {
    aes::aes -hex -mode cbc -dir encrypt -key [string repeat \\0 16] -[string repeat \\0 15]
} -result cc45117986e38ae95944f9eeaa7b700b240fdd169eacd2a20505ef4c6507c907

test aes-sf-3574004-b {aes use with data starting with a dash, double-dash} -body {
    aes::aes -hex -mode cbc -dir encrypt -key [string repeat \\0 16] -- -[string repeat \\0 15]
} -result cc45117986e38ae95944f9eeaa7b700b240fdd169eacd2a20505ef4c6507c907

# -------------------------------------------------------------------------
## TODO: Go through the various possible options and combinations.

test aes-sf-3612645-a0 {aes use of -in option, allura 1366} -setup {
    set key     [binary format a32 0123456789012345678901234567890123456789]
    set encfile [tcltest::makeFile {} aes.encrypt]
    set decfile [tcltest::makeFile {} aes.decrypt]
    set outchan [open $encfile w]
    fconfigure $outchan -translation binary
    aes::aes -key $key -out $outchan "Hello World Tcl"
    close $outchan
    unset outchan
} -body {
    set inchan  [open $encfile r]
    fconfigure $inchan -translation binary
    set outchan [open $decfile w+]
    aes::aes -dir decrypt -key $key -in $inchan -out $outchan
    close $inchan
    close $outchan
    viewFile $decfile
} -cleanup {
    file delete $encfile $decfile
    unset key encfile decfile inchan outchan
} -result "Hello World Tcl\000"

test aes-sf-3612645-a1 {aes use of -in option, allura 1366} -setup {
    set key     [binary format a32 0123456789012345678901234567890123456789]
    set encfile [tcltest::makeFile {} aes.encrypt]
    set outchan [open $encfile w]
    fconfigure $outchan -translation binary
    aes::aes -key $key -out $outchan "Hello World Tcl"
    close $outchan
    unset outchan
} -body {
    set inchan [open $encfile r]
    fconfigure $inchan -translation binary
    set out [aes::aes -dir decrypt -key $key -in $inchan]
    close $inchan
    set out
} -cleanup {
    file delete $encfile
    unset out key encfile inchan
} -result "Hello World Tcl\000"

test aes-sf-3612645-b0 {aes non-use of -in option, allura 1366} -setup {
    set key     [binary format a32 0123456789012345678901234567890123456789]
    set encfile [tcltest::makeFile {} aes.encrypt]
    set decfile [tcltest::makeFile {} aes.decrypt]
    set outchan [open $encfile w]
    fconfigure $outchan -translation binary
    aes::aes -key $key -out $outchan "Hello World Tcl"
    close $outchan
    unset outchan
} -body {
    set inchan  [open $encfile r]
    fconfigure $inchan -translation binary
    set outchan [open $decfile w+]
    aes::aes -dir decrypt -key $key -out $outchan [read $inchan]
    close $inchan
    close $outchan
    viewFile $decfile
} -cleanup {
    file delete $encfile $decfile
    unset key encfile decfile inchan outchan
} -result "Hello World Tcl\000"

test aes-sf-3612645-b1 {aes non-use of -in option, allura 1366} -setup {
    set key     [binary format a32 0123456789012345678901234567890123456789]
    set encfile [tcltest::makeFile {} aes.encrypt]
    set outchan [open $encfile w]
    fconfigure $outchan -translation binary
    aes::aes -key $key -out $outchan "Hello World Tcl"
    close $outchan
    unset outchan
} -body {
    set inchan [open $encfile r]
    fconfigure $inchan -translation binary
    set out [aes::aes -dir decrypt -key $key [read $inchan]]
    close $inchan
    set out
} -cleanup {
    file delete $encfile
    unset out key encfile inchan
} -result "Hello World Tcl\000"

# -------------------------------------------------------------------------









testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

|
>
>
>
>
>
>
>
>
>
>

















|




>


>
>
>
>
>
>
>
>
>
>
|

|

|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|

|
|
|

|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# aes.test - Copyright (c) 2005 Thorsten Schloermann

# Copyright (C) 2022-204 Nathan Coulter <[email protected]> 
#	ethereum 0x0b5049C148b00a216B29641ab16953b6060Ef8A6

# You may distribute and/or modify this program under the terms of the Software
# Utilization License version 3 or (at your option) any later version.
#
# See the file "license_fsul.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.


# the test-values are taken from:
#     http://csrc.nist.gov/CryptoToolkit/aes/rijndael/rijndael-vals.zip
#     where only the first 12 entries of Know Answer Test for variable key and
#     variable text are used
#     Unfortunately, only encryption is tested by this.
#
#
# Monte Carlo Tests with 4 Million cycles through the algorithm will need too much time
#
# $Id: aes.test,v 1.8 2010/07/06 19:39:00 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.6-
testsNeedTcltest 2

testing {
    useLocal aes.tcl aes
    useLocal aesc.tcl aesc
}

apply [list {} {
    foreach accelerate {0 1} {
	if {$accelerate} {
	    aes::SwitchTo critcl
	    set impl critcl
	} else {
	    aes::SwitchTo tcl
	    set impl Tcl
	}

	# -------------------------------------------------------------------------

	# data for variable key KAT

	# Sample vectors from FIPS 197 specification document.
	#
	test [list aes-fips-C.1e $impl] {Test vector for AES-128 from FIPS-197 Appendix C.1} -setup {
	    set txt [binary format H* 00112233445566778899aabbccddeeff]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
	} -body {
	    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    catch {unset txt key enc r}
	} -result 69c4e0d86a7b0430d8cdb78070b4c55a

	test [list aes-fips-C.1d $impl] {Test vector for AES-128 from FIPS-197 Appendix C.1} -setup {
	    set txt [binary format H* 69c4e0d86a7b0430d8cdb78070b4c55a]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
	} -body {
	    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 00112233445566778899aabbccddeeff

	test [list aes-fips-C.2e $impl] {Test vector for AES-192 from FIPS-197 Appendix C.2} -setup {
	    set txt [binary format H* 00112233445566778899aabbccddeeff]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f1011121314151617]
	} -body {
	    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result dda97ca4864cdfe06eaf70a0ec0d7191

	test [list aes-fips-C.2d $impl] {Test vector for AES-192 from FIPS-197 Appendix C.2} -setup {
	    set txt [binary format H* dda97ca4864cdfe06eaf70a0ec0d7191]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f1011121314151617]
	} -body {
	    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 00112233445566778899aabbccddeeff

	test [list aes-fips-C.3e $impl] {Test vector for AES-256 from FIPS-197 Appendix C.3} -setup {
	    set txt [binary format H* 00112233445566778899aabbccddeeff]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f]
	} -body {
	    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 8ea2b7ca516745bfeafc49904b496089

	test [list aes-fips-C.3d $impl] {Test vector for AES-256 from FIPS-197 Appendix C.3} -setup {
	    set txt [binary format H* 8ea2b7ca516745bfeafc49904b496089]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f]
	} -body {
	    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 00112233445566778899aabbccddeeff

	test [list aes-kat-ecb-128e $impl] {Known answer tests - AES-128 ECB encryption} -setup {
	    set txt [binary format H* 000102030405060708090a0b0c0d0e0f]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
	} -body {
	    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 0a940bb5416ef045f1c39458c653ea5a

	test [list aes-kat-ecb-128d $impl] {Known answer tests - AES-128 ECB decryption} -setup {
	    set txt [binary format H* 0a940bb5416ef045f1c39458c653ea5a]
	    set key [binary format H* 000102030405060708090a0b0c0d0e0f]
	} -body {
	    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 000102030405060708090a0b0c0d0e0f

	test [list aes-kat-ecb-192e $impl] {Known answer tests - AES-192 ECB encryption} -setup {
	    set txt [binary format H* 000102030405060708090a0b0c0d0e0f]
	    set key [binary format H* 000102030405060708090A0B0C0D0E0F1011121314151617]
	} -body {
	    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 0060bffe46834bb8da5cf9a61ff220ae

	test [list aes-kat-ecb-192d $impl] {Known answer tests - AES-192 ECB decryption} -setup {
	    set txt [binary format H* 0060bffe46834bb8da5cf9a61ff220ae]
	    set key [binary format H* 000102030405060708090A0B0C0D0E0F1011121314151617]
	} -body {
	    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 000102030405060708090a0b0c0d0e0f

	test [list aes-kat-ecb-256e $impl] {Known answer tests - AES-256 ECB encryption} -setup {
	    set txt [binary format H* 000102030405060708090a0b0c0d0e0f]
	    set key [binary format H* 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F]
	} -body {
	    set enc [aes::aes -mode ecb -dir enc -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 5a6e045708fb7196f02e553d02c3a692

	test [list aes-kat-ecb-256d $impl] {Known answer tests - AES-256 ECB decryption} -setup {
	    set txt [binary format H* 5a6e045708fb7196f02e553d02c3a692]
	    set key [binary format H* 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F]
	} -body {
	    set enc [aes::aes -mode ecb -dir dec -key $key $txt]
	    binary scan $enc H* r
	    set r
	} -cleanup {
	    unset txt key enc r
	} -result 000102030405060708090a0b0c0d0e0f


	# N key ic plain cipher
	set vectors {
	    1 06a9214036b8a15b512e03d534120006 3dafba429d9eb430b422da802c9fac41
	      53696e676c6520626c6f636b206d7367 e353779c1079aeb82708942dbe77181a
	    2 c286696d887c9aa0611bbb3e2025a45a 562e17996d093d28ddb3ba695a2e6f58
	      000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
	      d296cd94c2cccf8a3a863028b5e1dc0a7586602d253cfff91b8266bea6d61ab1
	    3 6c3ea0477630ce21a2ce334aa746c2cd c782dc4c098c66cbd9cd27d825682c81
	      5468697320697320612034382d62797465206d657373616765202865786163746c7920332041455320626c6f636b7329
	      d0a02b3836451753d493665d33f0e8862dea54cdb293abc7506939276772f8d5021c19216bad525c8579695d83ba2684    
	    4 56e47a38c5598974bc46903dba290349 8ce82eefbea0da3c44699ed7db51b7d9
	      a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf
	      c30e32ffedc0774e6aff6af0869f71aa0f3af07a9a31a9c684db207eb0ef8e4e35907aa632c3ffdf868bb7b29d3d46ad83ce9f9a102ee99d49a53e87f4c3da55
	}

	foreach {n key iv pt ct} $vectors {
	    test [list aes-cbc-${n}e $impl] {RFC3602 AES-128 CBC mode encryption} -setup {
		set K [binary format H* $key]
		set I [binary format H* $iv]
	    } -body {
		set aes [aes::aes -mode cbc -dir enc -key $K -iv $I [binary format H* $pt]]
		binary scan $aes H* r
		set r
	    } -cleanup {
			catch {unset r K I aes}
	    } -result $ct
	    
	    test [list aes-cbc-${n}d $impl] {RFC3602 AES-128 CBC mode decryption} -setup {
		set K [binary format H* $key]
		set I [binary format H* $iv]
	    } -body {
		set aes [aes::aes -mode cbc -dir dec -key $K -iv $I [binary format H* $ct]]
		binary scan $aes H* r
		set r
	    } -cleanup {
			catch {unset r K I aes}
	    } -result $pt
	}

	# Known answer tests (CBC)
	#    0 00000000000000000000000000000000 00000000000000000000000000000000 
	#      00000000000000000000000000000000 8a05fc5e095af4848a08d328d3688e3d
	#    1 8a05fc5e095af4848a08d328d3688e3d 8a05fc5e095af4848a08d328d3688e3d
	#      204f17e2444381f6114ff53934c0bcd3 192d9b3aa10bb2f7846ccba0085c657a
	#    2 93286764a85146730e641888db34eb47 192d9b3aa10bb2f7846ccba0085c657a
	#      983bf6f5a6dfbcdaa19370666e83a99a 40d8daf6d1fda0a073b3bd18b7695d2e
	#    3 d3f0bd9279ace6d37dd7a5906c5db669 40d8daf6d1fda0a073b3bd18b7695d2e
	#      c48cd503a21c8ad0b2483ef15f79571d 3edbe80d69a1d2248ca55fc17c4ef3c5

	# Bugs

	# N key ic plain cipher
	set vectors {
	    1
	    3132333435363738393031323334353637383930313233343536373839303132
	    c3f0929f353c2fc78b9c6705397f22c8
	    005a0000003b00000000000000000000
	    97d94ab5d6a6bf3e9a126b67b8b3bc12
	}

	foreach {n key iv pt ct} $vectors {
	    test [list aes-cbc-x${n}e $impl] {RFC3602 AES-128 CBC mode encryption} -setup {
		set K [binary format H* $key]
		set I [binary format H* $iv]
	    } -body {
		set aes [aes::aes -mode cbc -dir enc -key $K -iv $I [binary format H* $pt]]
		binary scan $aes H* r
		set r
	    } -cleanup {
		catch {unset r K I aes}
	    } -result $ct
	    
	    test [list aes-cbc-x${n}d $impl] {RFC3602 AES-128 CBC mode decryption} -setup {
		set K [binary format H* $key]
		set I [binary format H* $iv]
	    } -body {
		set aes [aes::aes -mode cbc -dir dec -key $K -iv $I [binary format H* $ct]]
		binary scan $aes H* r
		set r
	    } -cleanup {
		catch {unset r K I aes}
	    } -result $pt
	}

	test [list aes-sf2993029 $impl] {aes decrypt, wide integer, sf bug 2993029} -body {
	    aes::aes -hex -mode ecb -dir decrypt \
		-key [binary format H* FEDCBA98FEDCBA98FEDCBA98FEDCBA98] \
		[binary format H* 2a666624a86d4c29de37b520781c1069]
	} -result 01000000000000003d5afbb584a29f57

	# -------------------------------------------------------------------------

	test [list aes-sf-3574004-a $impl] {aes use with data starting with a dash, auto-stop} -body {
	    aes::aes -hex -mode cbc -dir encrypt -key [string repeat \\0 16] -[string repeat \\0 15]
	} -result cc45117986e38ae95944f9eeaa7b700b240fdd169eacd2a20505ef4c6507c907

	test [list aes-sf-3574004-b $impl] {aes use with data starting with a dash, double-dash} -body {
	    aes::aes -hex -mode cbc -dir encrypt -key [string repeat \\0 16] -- -[string repeat \\0 15]
	} -result cc45117986e38ae95944f9eeaa7b700b240fdd169eacd2a20505ef4c6507c907

	# -------------------------------------------------------------------------
	## TODO: Go through the various possible options and combinations.

	test [list aes-sf-3612645-a0 $impl] {aes use of -in option, allura 1366} -setup {
	    set key     [binary format a32 0123456789012345678901234567890123456789]
	    set encfile [tcltest::makeFile {} aes.encrypt]
	    set decfile [tcltest::makeFile {} aes.decrypt]
	    set outchan [open $encfile w]
	    fconfigure $outchan -translation binary
	    aes::aes -key $key -out $outchan "Hello World Tcl"
	    close $outchan
	    unset outchan
	} -body {
	    set inchan  [open $encfile r]
	    fconfigure $inchan -translation binary
	    set outchan [open $decfile w+]
	    aes::aes -dir decrypt -key $key -in $inchan -out $outchan
	    close $inchan
	    close $outchan
	    viewFile $decfile
	} -cleanup {
	    file delete $encfile $decfile
	    unset key encfile decfile inchan outchan
	} -result "Hello World Tcl\000"

	test [list aes-sf-3612645-a1 $impl] {aes use of -in option, allura 1366} -setup {
	    set key     [binary format a32 0123456789012345678901234567890123456789]
	    set encfile [tcltest::makeFile {} aes.encrypt]
	    set outchan [open $encfile w]
	    fconfigure $outchan -translation binary
	    aes::aes -key $key -out $outchan "Hello World Tcl"
	    close $outchan
	    unset outchan
	} -body {
	    set inchan [open $encfile r]
	    fconfigure $inchan -translation binary
	    set out [aes::aes -dir decrypt -key $key -in $inchan]
	    close $inchan
	    set out
	} -cleanup {
	    file delete $encfile
	    unset out key encfile inchan
	} -result "Hello World Tcl\000"

	test [list aes-sf-3612645-b0 $impl] {aes non-use of -in option, allura 1366} -setup {
	    set key     [binary format a32 0123456789012345678901234567890123456789]
	    set encfile [tcltest::makeFile {} aes.encrypt]
	    set decfile [tcltest::makeFile {} aes.decrypt]
	    set outchan [open $encfile w]
	    fconfigure $outchan -translation binary
	    aes::aes -key $key -out $outchan "Hello World Tcl"
	    close $outchan
	    unset outchan
	} -body {
	    set inchan  [open $encfile r]
	    fconfigure $inchan -translation binary
	    set outchan [open $decfile w+]
	    aes::aes -dir decrypt -key $key -out $outchan [read $inchan]
	    close $inchan
	    close $outchan
	    viewFile $decfile
	} -cleanup {
	    file delete $encfile $decfile
	    unset key encfile decfile inchan outchan
	} -result "Hello World Tcl\000"

	test [list aes-sf-3612645-b1 $impl] {aes non-use of -in option, allura 1366} -setup {
	    set key     [binary format a32 0123456789012345678901234567890123456789]
	    set encfile [tcltest::makeFile {} aes.encrypt]
	    set outchan [open $encfile w]
	    fconfigure $outchan -translation binary
	    aes::aes -key $key -out $outchan "Hello World Tcl"
	    close $outchan
	    unset outchan
	} -body {
	    set inchan [open $encfile r]
	    fconfigure $inchan -translation binary
	    set out [aes::aes -dir decrypt -key $key [read $inchan]]
	    close $inchan
	    set out
	} -cleanup {
	    file delete $encfile
	    unset out key encfile inchan
	} -result "Hello World Tcl\000"

	# -------------------------------------------------------------------------


    }


} [namespace current]]



testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

Added modules/aes/aesc.tcl.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
# aesc.tcl -

# A critcl C implementation of AES
#
# Copyright (C) 2022-2024 Nathan Coulter <[email protected]> 
#	ethereum 0x0b5049C148b00a216B29641ab16953b6060Ef8A6

# See the file "license_fsul.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 9
package require critcl
# @sak notprovided aesc
package provide aesc 0.2.0

namespace eval ::aes {
	critcl::tcl 9 
	critcl::ccode {
		#include <stdint.h>
		#include <string.h>

		#define AES_IVSIZE 16


		static Tcl_FreeInternalRepProc	AesFreeInternalRep;
		static Tcl_UpdateStringProc		AesUpdateStringRep;

		typedef enum aes_mode {CBC, ECB} aes_mode;
		char *aes_mode_strings[] = {"cbc" ,"ecb"};

		static Tcl_ObjType aesObjType =  {
			"aes",
			AesFreeInternalRep,
			NULL,
			AesUpdateStringRep,
			NULL,
			0, NULL
		};

		static Tcl_ObjType *aesObjTypePtr = &aesObjType;

		typedef struct aes_ctxt {
			aes_mode mode;
			int Nk;	/* number of 32-bit segments in the key */
			int Nr;	/* number of rounds (depends on key length) */
			int Nb; /* columns of the text-block, is always 4 in AES */
			uint_fast32_t I[4];
			uint_fast32_t *WPtr;
		} aes_ctxt;

		int aes_addRoundKey(Tcl_Interp *interp ,int round 
			,int Nb ,uint_fast32_t data[4] ,uint_fast32_t WPtr[]);
		int aes_expandkey(aes_ctxt* ctxt ,char *keystring); 
		int aes_decrypt(Tcl_Interp *interp ,int n ,unsigned char *bytes
			,int len ,uint_fast32_t* iv ,uint_fast32_t WPtr[] ,aes_mode);
		int aes_decryptBlock(Tcl_Interp *interp ,int n
			,unsigned char *bytes ,uint_fast32_t iv[4] ,Tcl_Size i, uint_fast32_t WPtr[]
			,aes_mode mode);
		aes_ctxt* aes_fetchCtxt(Tcl_Interp *interp ,Tcl_Obj *ctxtObjPtr);
		int aes_prepare(Tcl_Interp *interp ,aes_ctxt *ctxtPtr ,Tcl_Obj *data
			,unsigned char **bytes , Tcl_Size *len , Tcl_Obj **resObjPtr);
		void aes_clamp32(uint_fast32_t data[4]);
		int aes_encryptBlock(Tcl_Interp *interp
			,unsigned char *bytes ,aes_ctxt *ctxtPtr, Tcl_Size i
			,uint_fast32_t WPtr[] ,int n ,aes_mode moden);
		uint_fast32_t aes_GFMult2(uint_fast32_t number);
		uint_fast32_t aes_GFMult3(uint_fast32_t number);
		uint_fast32_t aes_GFMult09(uint_fast32_t number);
		uint_fast32_t aes_GFMult0b(uint_fast32_t number);
		uint_fast32_t aes_GFMult0d(uint_fast32_t number);
		uint_fast32_t aes_GFMult0e(uint_fast32_t number);

		void aes_invMixColumns(uint_fast32_t data[4]);
		void aes_invShiftRows(uint_fast32_t data[4]);
		void aes_invSubBytes(uint_fast32_t data[4]);
		uint_fast32_t aes_invSubWord(uint_fast32_t word);
		void aes_mixColumns(uint_fast32_t data[4]);
		uint_fast32_t aes_RotWord (uint_fast32_t w);
		void aes_shiftRows(uint_fast32_t data[4]);
		void aes_subBytes(uint_fast32_t data[4]);
		uint_fast32_t aes_SubWord(uint_fast32_t word);

		uint_fast8_t sbox[] = {
			 0x63 ,0x7c ,0x77 ,0x7b ,0xf2 ,0x6b ,0x6f ,0xc5 ,0x30 ,0x01 ,0x67 ,0x2b ,0xfe ,0xd7 ,0xab ,0x76
			,0xca ,0x82 ,0xc9 ,0x7d ,0xfa ,0x59 ,0x47 ,0xf0 ,0xad ,0xd4 ,0xa2 ,0xaf ,0x9c ,0xa4 ,0x72 ,0xc0
			,0xb7 ,0xfd ,0x93 ,0x26 ,0x36 ,0x3f ,0xf7 ,0xcc ,0x34 ,0xa5 ,0xe5 ,0xf1 ,0x71 ,0xd8 ,0x31 ,0x15
			,0x04 ,0xc7 ,0x23 ,0xc3 ,0x18 ,0x96 ,0x05 ,0x9a ,0x07 ,0x12 ,0x80 ,0xe2 ,0xeb ,0x27 ,0xb2 ,0x75
			,0x09 ,0x83 ,0x2c ,0x1a ,0x1b ,0x6e ,0x5a ,0xa0 ,0x52 ,0x3b ,0xd6 ,0xb3 ,0x29 ,0xe3 ,0x2f ,0x84
			,0x53 ,0xd1 ,0x00 ,0xed ,0x20 ,0xfc ,0xb1 ,0x5b ,0x6a ,0xcb ,0xbe ,0x39 ,0x4a ,0x4c ,0x58 ,0xcf
			,0xd0 ,0xef ,0xaa ,0xfb ,0x43 ,0x4d ,0x33 ,0x85 ,0x45 ,0xf9 ,0x02 ,0x7f ,0x50 ,0x3c ,0x9f ,0xa8
			,0x51 ,0xa3 ,0x40 ,0x8f ,0x92 ,0x9d ,0x38 ,0xf5 ,0xbc ,0xb6 ,0xda ,0x21 ,0x10 ,0xff ,0xf3 ,0xd2
			,0xcd ,0x0c ,0x13 ,0xec ,0x5f ,0x97 ,0x44 ,0x17 ,0xc4 ,0xa7 ,0x7e ,0x3d ,0x64 ,0x5d ,0x19 ,0x73
			,0x60 ,0x81 ,0x4f ,0xdc ,0x22 ,0x2a ,0x90 ,0x88 ,0x46 ,0xee ,0xb8 ,0x14 ,0xde ,0x5e ,0x0b ,0xdb
			,0xe0 ,0x32 ,0x3a ,0x0a ,0x49 ,0x06 ,0x24 ,0x5c ,0xc2 ,0xd3 ,0xac ,0x62 ,0x91 ,0x95 ,0xe4 ,0x79
			,0xe7 ,0xc8 ,0x37 ,0x6d ,0x8d ,0xd5 ,0x4e ,0xa9 ,0x6c ,0x56 ,0xf4 ,0xea ,0x65 ,0x7a ,0xae ,0x08
			,0xba ,0x78 ,0x25 ,0x2e ,0x1c ,0xa6 ,0xb4 ,0xc6 ,0xe8 ,0xdd ,0x74 ,0x1f ,0x4b ,0xbd ,0x8b ,0x8a
			,0x70 ,0x3e ,0xb5 ,0x66 ,0x48 ,0x03 ,0xf6 ,0x0e ,0x61 ,0x35 ,0x57 ,0xb9 ,0x86 ,0xc1 ,0x1d ,0x9e
			,0xe1 ,0xf8 ,0x98 ,0x11 ,0x69 ,0xd9 ,0x8e ,0x94 ,0x9b ,0x1e ,0x87 ,0xe9 ,0xce ,0x55 ,0x28 ,0xdf
			,0x8c ,0xa1 ,0x89 ,0x0d ,0xbf ,0xe6 ,0x42 ,0x68 ,0x41 ,0x99 ,0x2d ,0x0f ,0xb0 ,0x54 ,0xbb ,0x16
		};

		uint_fast8_t xobs[]  = {
			 0x52 ,0x09 ,0x6a ,0xd5 ,0x30 ,0x36 ,0xa5 ,0x38 ,0xbf ,0x40 ,0xa3 ,0x9e ,0x81 ,0xf3 ,0xd7 ,0xfb
			,0x7c ,0xe3 ,0x39 ,0x82 ,0x9b ,0x2f ,0xff ,0x87 ,0x34 ,0x8e ,0x43 ,0x44 ,0xc4 ,0xde ,0xe9 ,0xcb
			,0x54 ,0x7b ,0x94 ,0x32 ,0xa6 ,0xc2 ,0x23 ,0x3d ,0xee ,0x4c ,0x95 ,0x0b ,0x42 ,0xfa ,0xc3 ,0x4e
			,0x08 ,0x2e ,0xa1 ,0x66 ,0x28 ,0xd9 ,0x24 ,0xb2 ,0x76 ,0x5b ,0xa2 ,0x49 ,0x6d ,0x8b ,0xd1 ,0x25
			,0x72 ,0xf8 ,0xf6 ,0x64 ,0x86 ,0x68 ,0x98 ,0x16 ,0xd4 ,0xa4 ,0x5c ,0xcc ,0x5d ,0x65 ,0xb6 ,0x92
			,0x6c ,0x70 ,0x48 ,0x50 ,0xfd ,0xed ,0xb9 ,0xda ,0x5e ,0x15 ,0x46 ,0x57 ,0xa7 ,0x8d ,0x9d ,0x84
			,0x90 ,0xd8 ,0xab ,0x00 ,0x8c ,0xbc ,0xd3 ,0x0a ,0xf7 ,0xe4 ,0x58 ,0x05 ,0xb8 ,0xb3 ,0x45 ,0x06
			,0xd0 ,0x2c ,0x1e ,0x8f ,0xca ,0x3f ,0x0f ,0x02 ,0xc1 ,0xaf ,0xbd ,0x03 ,0x01 ,0x13 ,0x8a ,0x6b
			,0x3a ,0x91 ,0x11 ,0x41 ,0x4f ,0x67 ,0xdc ,0xea ,0x97 ,0xf2 ,0xcf ,0xce ,0xf0 ,0xb4 ,0xe6 ,0x73
			,0x96 ,0xac ,0x74 ,0x22 ,0xe7 ,0xad ,0x35 ,0x85 ,0xe2 ,0xf9 ,0x37 ,0xe8 ,0x1c ,0x75 ,0xdf ,0x6e
			,0x47 ,0xf1 ,0x1a ,0x71 ,0x1d ,0x29 ,0xc5 ,0x89 ,0x6f ,0xb7 ,0x62 ,0x0e ,0xaa ,0x18 ,0xbe ,0x1b
			,0xfc ,0x56 ,0x3e ,0x4b ,0xc6 ,0xd2 ,0x79 ,0x20 ,0x9a ,0xdb ,0xc0 ,0xfe ,0x78 ,0xcd ,0x5a ,0xf4
			,0x1f ,0xdd ,0xa8 ,0x33 ,0x88 ,0x07 ,0xc7 ,0x31 ,0xb1 ,0x12 ,0x10 ,0x59 ,0x27 ,0x80 ,0xec ,0x5f
			,0x60 ,0x51 ,0x7f ,0xa9 ,0x19 ,0xb5 ,0x4a ,0x0d ,0x2d ,0xe5 ,0x7a ,0x9f ,0x93 ,0xc9 ,0x9c ,0xef
			,0xa0 ,0xe0 ,0x3b ,0x4d ,0xae ,0x2a ,0xf5 ,0xb0 ,0xc8 ,0xeb ,0xbb ,0x3c ,0x83 ,0x53 ,0x99 ,0x61
			,0x17 ,0x2b ,0x04 ,0x7e ,0xba ,0x77 ,0xd6 ,0x26 ,0xe1 ,0x69 ,0x14 ,0x63 ,0x55 ,0x21 ,0x0c ,0x7d
		};


		/* this is a tabular representation of xtime (multiplication by 2)
		 * it is used instead of calculation to prevent timing attacks */

		uint8_t xtime[] = {
			0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
			0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 
			0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
			0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 
			0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 
			0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 
			0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, 
			0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 
			0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, 
			0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, 
			0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 
			0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, 
			0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, 
			0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 
			0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, 
			0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
		};

		uint32_t Rcon[] = {
			0x00000000 ,0x01000000 ,0x02000000 ,0x04000000 ,0x08000000
			,0x10000000 ,0x20000000 ,0x40000000 ,0x80000000 ,0x1b000000
			,0x36000000 ,0x6c000000 ,0xd8000000 ,0xab000000 ,0x4d000000
		};


		static void
		AesFreeInternalRep(
			Tcl_Obj *objPtr
		) {
			aes_ctxt *ctxtPtr = aes_fetchCtxt(NULL ,objPtr);
			if (ctxtPtr->WPtr) {
				Tcl_Free(ctxtPtr->WPtr);
			}
			Tcl_Free(ctxtPtr);
			return;
		}


		static void
		AesUpdateStringRep(
			Tcl_Obj *objPtr
		) {
			aes_ctxt *ctxtPtr = aes_fetchCtxt(NULL ,objPtr);
			char *tmpbytes = objPtr->bytes;
			Tcl_Size tmplength = objPtr->length;
			Tcl_Obj *tmpPtr = Tcl_ObjPrintf("aes context %p" ,ctxtPtr);
			objPtr->bytes = tmpPtr->bytes;
			objPtr->length = tmpPtr->length;
			tmpPtr->bytes = tmpbytes; 
			tmpPtr->length = tmplength;
			Tcl_DecrRefCount(tmpPtr);
			return;
		}


		int aes_addRoundKey(Tcl_Interp * interp ,int round
			,int Nb, uint_fast32_t data[4] ,uint_fast32_t WPtr[]) {
			Tcl_Obj *item;
			int i ,n ,status ,w;
			uint_fast32_t uword;
			n = round * Nb;

			for (i = 0 ;i < Nb ;i++) {
				uword = WPtr[n];
				data[i] = data[i] ^ uword;
				n++;
			}
			return TCL_OK;
		}


		void aes_clamp32(uint_fast32_t data[4]) {
			/* Force all elements into 32bit range. */
			data[0] = data[0] & 0xffffffff;
			data[1] = data[1] & 0xffffffff;
			data[2] = data[2] & 0xffffffff;
			data[3] = data[3] & 0xffffffff;
			return;
		}


		int aes_decrypt(Tcl_Interp *interp ,int n ,unsigned char *bytes
			,int len ,uint_fast32_t* iv ,uint_fast32_t WPtr[] ,aes_mode moden) {
			int i ,status;
			for (i = 0 ;i < len ;i+= 16) {
				status = aes_decryptBlock(interp ,n ,bytes ,iv ,i ,WPtr ,moden);
				if (status != TCL_OK) {
					return TCL_ERROR;
				}
			}
			return TCL_OK;
		}


		int aes_decryptBlock(Tcl_Interp *interp, int n
			, unsigned char *bytes ,uint_fast32_t iv[4] ,Tcl_Size i
			,uint_fast32_t WPtr[] ,aes_mode mode) {

			Tcl_Obj *formattedPtr;
			int status;
			Tcl_Size k = i;
			uint_fast8_t j;
			uint_fast32_t data[4] ,newdata[4], newiv[4];

			for (j = 0 ;j < 4 ;j++) {
				newiv[j] = data[j] =  bytes[k++] << 24 | bytes[k++] << 16
					| bytes[k++] << 8 | bytes[k++];
			}
			status = aes_addRoundKey(interp ,n ,4 ,data ,WPtr);
			if (status != TCL_OK) {
				return status;
			};
			for (n-- ;n > 0 ;n--) {
				aes_invShiftRows(data);
				aes_invSubBytes(data);
				status = aes_addRoundKey(interp ,n ,4 ,data ,WPtr);
				if (status != TCL_OK) {
					return status;
				}
				aes_invMixColumns(data);
			}
			aes_invShiftRows(data);
			aes_invSubBytes(data);
			status = aes_addRoundKey(interp ,n ,4 ,data ,WPtr);
			if (status != TCL_OK) {
				return status;
			}

			switch (mode) {
				case CBC:
					data[0] =(data[0] ^ iv[0]) & 0xffffffff;
					data[1] =(data[1] ^ iv[1]) & 0xffffffff;
					data[2] =(data[2] ^ iv[2]) & 0xffffffff;
					data[3] =(data[3] ^ iv[3]) & 0xffffffff;
					break;
				default:
					aes_clamp32(data);
					break;
			}

			k = i;
			for (j = 0 ;j < 4 ;j++) {
				bytes[k++] = data[j] >> 24 & 255;
				bytes[k++] = data[j] >> 16 & 255;
				bytes[k++] = data[j] >> 8 & 255;
				bytes[k++] = data[j] & 255;
			}
			memcpy(iv ,newiv ,sizeof(newiv));
			return TCL_OK;
		}


		int aes_encryptBlock(Tcl_Interp *interp ,unsigned char *bytes
			,aes_ctxt *ctxtPtr, Tcl_Size i ,uint_fast32_t WPtr[] ,int n
			,aes_mode moden) {

			int status;
			Tcl_Size k = i;
			uint8_t j;
			uint_fast32_t data[4] ,newiv[4];
			uint_fast32_t *IPtr = ctxtPtr->I;

			for (j = 0 ;j < 4 ;j++) {
				newiv[j] = data[j] =  bytes[k++] << 24 | bytes[k++] << 16
					| bytes[k++] << 8 | bytes[k++];
			}

			switch (moden) {
				case CBC:
					data[0] = data[0] ^ IPtr[0];
					data[1] = data[1] ^ IPtr[1];
					data[2] = data[2] ^ IPtr[2];
					data[3] = data[3] ^ IPtr[3];
					break;
			}

			status = aes_addRoundKey(interp ,0 ,4 ,data ,WPtr);

			if (status != TCL_OK) {
				return status;
			};
			for (j = 1 ;j < n ;j++) {
				aes_subBytes(data);
				aes_shiftRows(data);
				aes_mixColumns(data);
				aes_addRoundKey(interp ,j ,4 ,data ,WPtr);
			}
			aes_subBytes(data);
			aes_shiftRows(data);
			aes_addRoundKey(interp ,j ,4 ,data ,WPtr);

			/* Bug 2993029:
			* Force all elements of data into the 32bit range.
			* Loop unrolled
			*/
			aes_clamp32(data);
			k = i;
			for (j = 0 ;j < 4 ;j++) {
				bytes[k++] = data[j] >> 24 & 255;
				bytes[k++] = data[j] >> 16 & 255;
				bytes[k++] = data[j] >> 8 & 255;
				bytes[k++] = data[j] & 255;
			}
			memcpy(IPtr ,data ,sizeof(data));
			return TCL_OK;
		}


		uint_fast32_t aes_GFMult2(uint_fast32_t number) {
			return xtime[number];
		}


		uint_fast32_t aes_GFMult3(uint_fast32_t number) {
			/* multliply by 2 (via aes_GFMult2) and add the number again on
			 * the result (via XOR) */
			return number ^ aes_GFMult2(number);
		}


		uint_fast32_t aes_GFMult09(uint_fast32_t number) {
			/* 09 is: (02*02*02) + 01 */
			return aes_GFMult2(aes_GFMult2(aes_GFMult2(number))) ^ number;
		}


		uint_fast32_t aes_GFMult0b(uint_fast32_t number) {
			/*
			0b is: (02*02*02) + 02 + 01
			*/
			return aes_GFMult09(number) ^ aes_GFMult2(number);
		}


		uint_fast32_t aes_GFMult0d(uint_fast32_t number) {
			/* 0d is: (02*02*02) + (02*02) + 01 */
			uint_fast32_t temp;
			temp = aes_GFMult2(aes_GFMult2(number));
			return aes_GFMult2(temp) ^ (temp ^ number);
		}


		uint_fast32_t aes_GFMult0e(uint_fast32_t number) {
			/* 0e is: (02*02*02) + (02*02) + 02 */
			uint_fast32_t temp;
			temp = aes_GFMult2(aes_GFMult2(number));
			return aes_GFMult2(temp) ^ (temp ^ aes_GFMult2(number));
		}


		int aes_expandkey(aes_ctxt* ctxtPtr ,char *keystring) {
			uint_fast32_t mask = 0xffffffff;
			uint_fast32_t rc ,sub ,temp;
			uint_fast32_t h ,i ,j ,max;
			max = ctxtPtr->Nb * (ctxtPtr->Nr + 1);
			uint_fast32_t *W = Tcl_Alloc(sizeof(uint_fast32_t) * (ctxtPtr->Nk + max));
			ctxtPtr->WPtr = W;

			for (i = 0 ,j = 0; i < ctxtPtr->Nk; i++, j+=4) {
				int chanmode;
				temp = (uint8_t)keystring[j] << 24;
				temp += (uint8_t)keystring[j+1] << 16;
				temp += (uint8_t)keystring[j+2] << 8;
				temp += (uint8_t)keystring[j+3];
				W[i] = temp;
			}

			h= i - 1;
			j = 0;
			for (;i < max; i+= 1 ,h += 1 ,j += 1) {
				temp = W[h];
				if ((i % ctxtPtr->Nk) == 0) {
					sub = aes_SubWord(aes_RotWord(temp));
					rc = Rcon[i/ctxtPtr->Nk];
					temp = sub ^ rc;
				} else if (ctxtPtr->Nk > 6 && (i % ctxtPtr->Nk) == 4) {
					temp = aes_SubWord(temp);
				}
				W[i] = W[j] ^ temp;
			}
			return TCL_OK;
		}


		aes_ctxt* aes_fetchCtxt(Tcl_Interp *interp ,Tcl_Obj *ctxtObjPtr) {
			aes_ctxt *ctxtPtr;
			Tcl_ObjInternalRep *ir = Tcl_FetchInternalRep(ctxtObjPtr ,aesObjTypePtr);
			if (!ir) {
				if (interp) {
					Tcl_SetObjResult(interp, Tcl_NewStringObj(
						"value does not provide an aes context", -1));
				}
				return NULL;
			}
			ctxtPtr = ir->twoPtrValue.ptr1;
			return ctxtPtr;
		}



		void aes_invMixColumns(uint_fast32_t data[4]) {
			uint_fast8_t i ,r0 ,r1 ,r2 ,r3 ,s0 ,s1 ,s2 ,s3;
			for (i=0 ;i < 4 ;i++) {
				r0 = (data[i] >> 24) & 255;
				r1 = (data[i] >> 16) & 255;
				r2 = (data[i] >> 8 ) & 255;
				r3 = data[i]         & 255;

				s0 = aes_GFMult0e(r0) ^ aes_GFMult0b(r1) ^ aes_GFMult0d(r2)
					^ aes_GFMult09(r3);
				s1 = aes_GFMult09(r0) ^ aes_GFMult0e(r1) ^ aes_GFMult0b(r2)
					^ aes_GFMult0d(r3);
				s2 = aes_GFMult0d(r0) ^ aes_GFMult09(r1) ^ aes_GFMult0e(r2)
					^ aes_GFMult0b(r3);
				s3 = aes_GFMult0b(r0) ^ aes_GFMult0d(r1) ^ aes_GFMult09(r2)
					^ aes_GFMult0e(r3);
				data[i] = (s0 << 24) | (s1 << 16) | (s2 << 8) | s3;
			}
			return;
		}


		void aes_invShiftRows(uint_fast32_t data[4]) {
			uint_fast8_t n0 ,n1 ,n2 ,n3;
			uint_fast32_t newdata[4];
			for (n0 = 0 ;n0 < 4 ;n0++) {
				n1 = (n0 + 1) % 4;
				n2 = (n0 + 2) % 4;
				n3 = (n0 + 3) % 4;
				newdata[n0] = 
					  (data[n0] & 0xff000000)
					| (data[n3] & 0x00ff0000)
					| (data[n2] & 0x0000ff00)
					| (data[n1] & 0x000000ff)
				;
			}
			memcpy(data ,newdata ,sizeof(newdata));
			return;
		}


		void aes_invSubBytes(uint_fast32_t data[4]) {
			data[0] = aes_invSubWord(data[0]);
			data[1] = aes_invSubWord(data[1]);
			data[2] = aes_invSubWord(data[2]);
			data[3] = aes_invSubWord(data[3]);
			return;
		}


		uint_fast32_t aes_invSubWord(uint_fast32_t word) {
			uint8_t s3, s2 ,s1 ,s0;
			s3 = xobs[(word >> 24) & 255];
			s2 = xobs[(word >> 16) & 255];
			s1 = xobs[(word >> 8) & 255];
			s0 = xobs[word  & 255];
			return (s3 << 24) | (s2 << 16) | (s1 << 8) | s0;
		}


		void aes_mixColumns(uint_fast32_t data[4]) {
			uint_fast8_t i ,r0 ,r1 ,r2 ,r3 ,s0 ,s1 ,s2 ,s3;
			for (i = 0 ;i < 4; i++) {
				r0 = (data[i] >> 24) & 255;
				r1 = (data[i] >> 16) & 255;
				r2 = (data[i] >> 8 ) & 255;
				r3 = data[i]        & 255;

				s0 = aes_GFMult2(r0) ^ aes_GFMult3(r1) ^ r2 ^ r3;
				s1 = r0 ^ aes_GFMult2(r1) ^ aes_GFMult3(r2) ^ r3;
				s2 = r0 ^ r1 ^ aes_GFMult2(r2) ^ aes_GFMult3(r3);
				s3 = aes_GFMult3(r0) ^ r1 ^ r2 ^ aes_GFMult2(r3);
				data[i] = (s0 << 24) | (s1 << 16) | (s2 << 8) | s3;
			}
			return;
		}


		int aes_prepare(Tcl_Interp *interp ,aes_ctxt *ctxtPtr, Tcl_Obj *dataPtr
			,unsigned char **bytes ,Tcl_Size *lenPtr ,Tcl_Obj **resObjPtr) {

			int i ,owned = 0, status = TCL_OK;

			if (Tcl_IsShared(dataPtr)) {
				*resObjPtr = Tcl_DuplicateObj(dataPtr);
				owned = 1;
			} else {
				*resObjPtr = dataPtr;
			}

			*bytes = Tcl_GetBytesFromObj(interp ,*resObjPtr, lenPtr);
			if (bytes == NULL) {
				Tcl_SetObjResult(interp ,Tcl_NewStringObj(
					"data must not include characters with\
						a code point greater than 255", -1));
				status = TCL_ERROR;
				goto failure;
			}
			if (*lenPtr % 16 != 0) {
				Tcl_SetObjResult(interp ,Tcl_NewStringObj(
					"invalid block size: AES requires 16 byte blocks", -1));
				status =  TCL_ERROR;
				goto failure;
			}

			goto success;
			failure:
				if (owned) {
					Tcl_DecrRefCount(*resObjPtr);
				}
				*resObjPtr = NULL;
			success:
				return status;
		}


		uint_fast32_t aes_RotWord (uint_fast32_t w) {
			return ((w << 8) | ((w >> 24) & 0xff)) & 0xffffffff;
		}


		void aes_shiftRows(uint_fast32_t data[4]) {
			uint_fast8_t n0 ,n1 ,n2 ,n3;
			uint_fast32_t newdata[4];
			for (n0 = 0 ;n0 < 4 ;n0++) {
				n1 = (n0 + 1) % 4;
				n2 = (n0 + 2) % 4;
				n3 = (n0 + 3) % 4;
				newdata[n0] = 
					  (data[n0] & 0xff000000)
					| (data[n1] & 0x00ff0000)
					| (data[n2] & 0x0000ff00)
					| (data[n3] & 0x000000ff);
			}
			memcpy(data ,newdata ,sizeof(newdata));
			return;
		}


		void aes_subBytes(uint_fast32_t data[4]) {
			data[0] = aes_SubWord(data[0]);
			data[1] = aes_SubWord(data[1]);
			data[2] = aes_SubWord(data[2]);
			data[3] = aes_SubWord(data[3]);
			return;
		}


		uint_fast32_t aes_SubWord(uint_fast32_t word) {
			uint_fast32_t s0 ,s1 ,s2 ,s3;
			s3 = sbox[(word >> 24) & 255];
			s2 = sbox[(word >> 16) & 255];
			s1 = sbox[(word >> 8) & 255];
			s0 = sbox[word & 255];
			return (s3 << 24) | (s2 << 16) | (s1 << 8) | s0;
		}

	}


    critcl::cproc EncryptAccelerated {
		Tcl_Interp* interp Tcl_Obj* handle Tcl_Obj* data
	} ok {
		unsigned char *bytes;
		int status = TCL_OK;
		Tcl_Size i, len;
		Tcl_Obj *resObjPtr;
		aes_ctxt *ctxtPtr = aes_fetchCtxt(interp , handle);
		if (!ctxtPtr) {
			return TCL_ERROR;
		}
		status = aes_prepare(interp ,ctxtPtr ,data ,&bytes ,&len ,&resObjPtr);
		if (status != TCL_OK) {
			return status;
		}
		for (i = 0 ;i < len ;i+= 16) {
			status = aes_encryptBlock(
				interp ,bytes ,ctxtPtr ,i ,ctxtPtr->WPtr ,ctxtPtr->Nr ,ctxtPtr->mode);
			if (status != TCL_OK) {
				goto failure;
			}
		}
		goto success;
		failure:
			Tcl_BounceRefCount(resObjPtr);
			return status;
		success:
			Tcl_SetByteArrayObj(resObjPtr ,bytes ,len);
			Tcl_SetObjResult(interp ,resObjPtr);
			return TCL_OK;
	}


    critcl::cproc DecryptAccelerated {
		Tcl_Interp* interp Tcl_Obj* handle Tcl_Obj* data
	} ok {
		char *modePtr;
		unsigned char *bytes;
		int j, n,status = TCL_OK;
		Tcl_Size i, len;
		uint_fast32_t uword ,*iv;
		Tcl_Obj *resObjPtr ,*itemPtr ,*listPtr ,*MPtr;
		aes_ctxt *ctxtPtr;
		static Tcl_Obj *IName;
		ctxtPtr = aes_fetchCtxt(interp , handle);
		if (!ctxtPtr) {
			return TCL_ERROR;
		}
		iv = ctxtPtr->I;

		status = aes_prepare(interp ,ctxtPtr ,data ,&bytes ,&len ,&resObjPtr);
		if (status != TCL_OK) {
			goto failure2;
		}

		aes_decrypt(interp ,ctxtPtr->Nr ,bytes ,len ,ctxtPtr->I ,ctxtPtr->WPtr
			,ctxtPtr->mode);

		Tcl_SetObjResult(interp ,resObjPtr);
		goto success;
		failure:
			Tcl_DecrRefCount(resObjPtr);
		failure2:
			return status;
		success:
			Tcl_SetByteArrayObj(resObjPtr ,bytes ,len);
			Tcl_SetObjResult(interp ,resObjPtr);
			return TCL_OK;
	}


	critcl::cproc FinalAccelerated {
		Tcl_Interp* interp Tcl_Obj* objPtr
	} ok {
		Tcl_FreeInternalRep(objPtr);
		return TCL_OK;
	}

	critcl::cproc InitAccelerated {
		Tcl_Interp* interp Tcl_Obj* mode Tcl_Obj* keyPtr Tcl_Obj* IPtr
	} object0 {
		int i ,j ,modeidx ,Nk ,Nr ,Nb = 4;
		uint_fast32_t ivval ,ivval2;
		Tcl_Obj *resultPtr;
		Tcl_Size ivlength, keylength;
		Tcl_ObjInternalRep ir;
		aes_ctxt *ctxtPtr;

		if (Tcl_IsShared(keyPtr)) {
			keyPtr = Tcl_DuplicateObj(keyPtr);
		}

		char *keystring = Tcl_GetBytesFromObj(interp ,keyPtr ,&keylength);
		if (!keystring) {
			return NULL;
		}
		switch (keylength << 3) {
			case 128:
				Nk=4; Nr=10;
				break;
			case 192:
				Nk=6; Nr=12;
				break;
			case 256:
				Nk=8; Nr=14;
				break;
			default:
				Tcl_SetObjResult(interp, Tcl_NewStringObj(
					"{the length of the key in bytes must be one of} {128 192 256}", -1));
				return NULL;
		}

		ctxtPtr = Tcl_Alloc(sizeof(aes_ctxt));
		char *ivstring = Tcl_GetBytesFromObj(interp ,IPtr ,&ivlength);
		Tcl_GetIndexFromObj(interp, mode, aes_mode_strings, "option", TCL_EXACT, &modeidx);
		switch (modeidx) {
			case CBC:
				if (ivlength == 0) {
					for (j = 0; j < 4; j++) {
						ctxtPtr->I[j] = 0;
					}
				} else {
					if (ivlength != 16) {
						Tcl_SetObjResult(interp, Tcl_NewStringObj(
							"the length of iv must be 16 bytes", -1));
						goto failure;
					}

					for (i = 0, j = 0; i < 4; i++ , j+=4) {
						ivval = ((uint8_t)ivstring[j+0]) << 24;
						ivval += ((uint8_t)ivstring[j+1]) << 16;
						ivval += ((uint8_t)ivstring[j+2]) << 8;
						ivval += ((uint8_t)ivstring[j+3]) << 0;
						ctxtPtr->I[i] = ivval;
					}
				}
				break;
			case ECB:
				if (ivlength != 0) {
					Tcl_SetObjResult(interp, Tcl_NewStringObj(
						"In ECB mod an initialization vector is not used", -1));
					goto failure;
				}
				for (j = 0; j < 4; j++) {
					ctxtPtr->I[j] = 0;
				}
				break;
			default:
				if (interp != NULL) {
					Tcl_SetObjResult(interp, Tcl_NewStringObj(
						"mode must be either \"cbc\" or \"ecb\"", -1));
					goto failure;
				}
				break;
		}

		ctxtPtr->mode = modeidx;
		ctxtPtr->Nk = Nk;
		ctxtPtr->Nr = Nr;
		ctxtPtr->Nb = Nb;

		aes_expandkey(ctxtPtr ,keystring);

		ir.twoPtrValue.ptr1 = ctxtPtr;
		resultPtr = Tcl_NewObj();
		Tcl_InvalidateStringRep(resultPtr);
		Tcl_StoreInternalRep(resultPtr, aesObjTypePtr, &ir);
		Tcl_GetStringFromObj(resultPtr ,NULL);
		return resultPtr;

		failure:
			Tcl_Free(ctxtPtr);
			return NULL;
	}

	critcl::debug symbols
	critcl::load

}

Changes to modules/aes/pkgIndex.tcl.

1
2
3
4
5

if {![package vsatisfies [package provide Tcl] 8.5 9]} {
    # PRAGMA: returnok
    return
}
package ifneeded aes 1.2.2 [list source [file join $dir aes.tcl]]





|
>
1
2
3
4
5
6
if {![package vsatisfies [package provide Tcl] 8.5 9]} {
    # PRAGMA: returnok
    return
}
package ifneeded aes 1.2.3 [list source [file join $dir aes.tcl]]
package ifneeded aesc 0.2.0 [list source [file join $dir aesc.tcl]]

Changes to modules/sha1/sha256c.tcl.

183
184
185
186
187
188
189
190
191
	uint32_t len
}
::critcl::api function void SHA256Final {
	SHA256Context *sc
	uint8_t *hash
}

#::critcl::debug symbols
::critcl::load







|

183
184
185
186
187
188
189
190
191
	uint32_t len
}
::critcl::api function void SHA256Final {
	SHA256Context *sc
	uint8_t *hash
}

::critcl::debug symbols
::critcl::load