aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ubicom32/files/arch/ubicom32/crypto/sha1_ubicom32_asm.S
blob: f610b7e9f1ca6cb3c72e77b45a5ade1494f4a092 (plain)
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
/*
 * arch/ubicom32/crypto/sha1_ubicom32_asm.S
 *	SHA1 hash support for Ubicom32 architecture V3.
 *
 * (C) Copyright 2009, Ubicom, Inc.
 *
 * This file is part of the Ubicom32 Linux Kernel Port.
 *
 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, either version 2 of the
 * License, or (at your option) any later version.
 *
 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 * the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the Ubicom32 Linux Kernel Port.  If not,
 * see <http://www.gnu.org/licenses/>.
 *
 * Ubicom32 implementation derived from (with many thanks):
 *   arch/m68knommu
 *   arch/blackfin
 *   arch/parisc
 */

#define __ASM__
#include <asm/ip5000.h>

#ifndef RP
#define RP A5
#endif

;*****************************************************************************************
; The function prototype
;*****************************************************************************************
; void sha1_ip5k_init(void)
; void sha1_ip5k_transform(u32_t *data_input)
; void sha1_ip5k_output(u32_t *digest)

;*****************************************************************************************
; Inputs
;*****************************************************************************************
; data_input is the pointer to the block of data over which the digest will be calculated.
;	It should be word aligned.
;
; digest is the pointer to the block of data into which the digest (the output) will be written.
;	It should be word aligned.
;

;*****************************************************************************************
; Outputs
;*****************************************************************************************
; None

;*****************************************************************************************
; Hash Constants
;*****************************************************************************************
#define HASH_SHA1_IN0 0x67452301
#define HASH_SHA1_IN1 0xefcdab89
#define HASH_SHA1_IN2 0x98badcfe
#define HASH_SHA1_IN3 0x10325476
#define HASH_SHA1_IN4 0xc3d2e1f0

#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)

;*****************************************************************************************
; An: Address Registers
;*****************************************************************************************
#define an_digest a4
#define an_data_input a4
#define an_security_block a3

;*****************************************************************************************
; Hash related defines
;*****************************************************************************************
#define hash_control 0x00(an_security_block)
#define hash_control_low 0x02(an_security_block)
#define hash_status 0x04(an_security_block)

#define hash_input_0 0x30(an_security_block)
#define hash_input_1 0x34(an_security_block)
#define hash_input_2 0x38(an_security_block)
#define hash_input_3 0x3c(an_security_block)
#define hash_input_4 0x40(an_security_block)

#define hash_output_0 0x70(an_security_block)
#define hash_output_0_low 0x72(an_security_block)
#define hash_output_1 0x74(an_security_block)
#define hash_output_1_low 0x76(an_security_block)
#define hash_output_2 0x78(an_security_block)
#define hash_output_2_low 0x7a(an_security_block)
#define hash_output_3 0x7c(an_security_block)
#define hash_output_3_low 0x7e(an_security_block)
#define hash_output_4 0x80(an_security_block)
#define hash_output_4_low 0x82(an_security_block)

;*****************************************************************************************
; Assembly macros
;*****************************************************************************************
	; C compiler reserves RP (A5) for return address during subroutine call.
	; Use RP to return to caller
.macro	call_return_macro
	calli	RP, 0(RP)
.endm

;*****************************************************************************************
;	void sha1_ip5k_init(void)
;		initialize the output registers of the hash module

	;.section .text.sha1_ip5k_init,"ax",@progbits
	.section .ocm_text,"ax",@progbits
	.global	_sha1_ip5k_init
	.func sha1_ip5k_init, _sha1_ip5k_init

_sha1_ip5k_init:
	moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS

	movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
	movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)

	movei hash_output_0, #%hi(HASH_SHA1_IN0)
	movei hash_output_0_low, #%lo(HASH_SHA1_IN0)

	movei hash_output_1, #%hi(HASH_SHA1_IN1)
	movei hash_output_1_low, #%lo(HASH_SHA1_IN1)

	movei hash_output_2, #%hi(HASH_SHA1_IN2)
	movei hash_output_2_low, #%lo(HASH_SHA1_IN2)

	movei hash_output_3, #%hi(HASH_SHA1_IN3)
	movei hash_output_3_low, #%lo(HASH_SHA1_IN3)

	movei hash_output_4, #%hi(HASH_SHA1_IN4)
	movei hash_output_4_low, #%lo(HASH_SHA1_IN4)

	call_return_macro
	.endfunc

;*****************************************************************************************
;	void sha1_ip5k_init_digest(u32_t *hash_input)
;		initialize the output registers of the hash module

	;.section .text.sha1_ip5k_init_digest,"ax",@progbits
	.section .ocm_text,"ax",@progbits
	.global	_sha1_ip5k_init_digest
	.func sha1_ip5k_init_digest, _sha1_ip5k_init_digest

_sha1_ip5k_init_digest:
	movea an_data_input, D0

	moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS

	movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
	movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)

	move.4 hash_output_0, (an_data_input)4++
	move.4 hash_output_1, (an_data_input)4++
	move.4 hash_output_2, (an_data_input)4++
	move.4 hash_output_3, (an_data_input)4++
	move.4 hash_output_4, (an_data_input)4++

	call_return_macro
	.endfunc

;*****************************************************************************************
;	void sha1_ip5k_transform(u32_t *data_input)
;		performs intermediate transformation step for the hash calculation

	;.section .text.sha1_ip5k_transform,"ax",@progbits
	.section .ocm_text,"ax",@progbits
	.global	_sha1_ip5k_transform
	.func sha1_ip5k_transform, _sha1_ip5k_transform

_sha1_ip5k_transform:
	movea an_data_input, D0

	moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS

	; Write the first 128bits (16 bytes)
	move.4 hash_input_0, (an_data_input)4++
	move.4 hash_input_1, (an_data_input)4++
	move.4 hash_input_2, (an_data_input)4++
	move.4 hash_input_3, (an_data_input)4++
	move.4 hash_input_4, D0

	move.4 hash_input_0, (an_data_input)4++
	move.4 hash_input_1, (an_data_input)4++
	move.4 hash_input_2, (an_data_input)4++
	move.4 hash_input_3, (an_data_input)4++
	move.4 hash_input_4, D0

	move.4 hash_input_0, (an_data_input)4++
	move.4 hash_input_1, (an_data_input)4++
	move.4 hash_input_2, (an_data_input)4++
	move.4 hash_input_3, (an_data_input)4++
	move.4 hash_input_4, D0

	move.4 hash_input_0, (an_data_input)4++
	move.4 hash_input_1, (an_data_input)4++
	move.4 hash_input_2, (an_data_input)4++
	move.4 hash_input_3, (an_data_input)4++
	move.4 hash_input_4, D0

	pipe_flush 0

sha1_ip5k_transform_wait:
	; wait for the module to calculate the output hash
	btst hash_status, #0
	jmpne.f sha1_ip5k_transform_wait

	call_return_macro
	.endfunc

;*****************************************************************************************
;	void sha1_ip5k_output(u32_t *digest)
;		Return the hash of the input data

	;.section .text.sha1_ip5k_output,"ax",@progbits
	.section .ocm_text,"ax",@progbits
	.global	_sha1_ip5k_output
	.func sha1_ip5k_output, _sha1_ip5k_output

_sha1_ip5k_output:
	movea an_digest, D0

	moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS

	; we have finished
	move.4 0(an_digest), hash_output_0
	move.4 4(an_digest), hash_output_1
	move.4 8(an_digest), hash_output_2
	move.4 12(an_digest), hash_output_3
	move.4 16(an_digest), hash_output_4

	call_return_macro
	.endfunc

;*****************************************************************************************
;END			;End of program code
;*****************************************************************************************