| 1 | /* |
| 2 | * arch/ubicom32/crypto/md5_ubicom32_asm.S |
| 3 | * MD5 (Message Digest 5) support for Ubicom32 v3 architecture |
| 4 | * |
| 5 | * (C) Copyright 2009, Ubicom, Inc. |
| 6 | * |
| 7 | * This file is part of the Ubicom32 Linux Kernel Port. |
| 8 | * |
| 9 | * The Ubicom32 Linux Kernel Port is free software: you can redistribute |
| 10 | * it and/or modify it under the terms of the GNU General Public License |
| 11 | * as published by the Free Software Foundation, either version 2 of the |
| 12 | * License, or (at your option) any later version. |
| 13 | * |
| 14 | * The Ubicom32 Linux Kernel Port is distributed in the hope that it |
| 15 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
| 16 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| 17 | * the GNU General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with the Ubicom32 Linux Kernel Port. If not, |
| 21 | * see <http://www.gnu.org/licenses/>. |
| 22 | * |
| 23 | * Ubicom32 implementation derived from (with many thanks): |
| 24 | * arch/m68knommu |
| 25 | * arch/blackfin |
| 26 | * arch/parisc |
| 27 | */ |
| 28 | |
| 29 | #define __ASM__ |
| 30 | #include <asm/ip5000.h> |
| 31 | |
| 32 | #ifndef RP |
| 33 | #define RP A5 |
| 34 | #endif |
| 35 | |
| 36 | ;***************************************************************************************** |
| 37 | ; The function prototypes |
| 38 | ;***************************************************************************************** |
| 39 | ; void md5_ip5k_init(void) |
| 40 | ; void md5_ip5k_transform(u32_t *data_input) |
| 41 | ; void md5_get_digest(u32_t *digest) |
| 42 | |
| 43 | ;***************************************************************************************** |
| 44 | ; Inputs |
| 45 | ;*****************************************************************************************; |
| 46 | ; data_input is the pointer to the block of data over which the digest will be calculated. |
| 47 | ; It should be word aligned. |
| 48 | ; |
| 49 | ; digest is the pointer to the block of data into which the digest (the output) will be written. |
| 50 | ; It should be word aligned. |
| 51 | ; |
| 52 | |
| 53 | ;***************************************************************************************** |
| 54 | ; Outputs |
| 55 | ;***************************************************************************************** |
| 56 | ; None |
| 57 | |
| 58 | ;***************************************************************************************** |
| 59 | ; An: Address Registers |
| 60 | ;***************************************************************************************** |
| 61 | #define an_digest A3 |
| 62 | #define an_data_input A3 |
| 63 | #define an_security_block A4 |
| 64 | |
| 65 | ;***************************************************************************************** |
| 66 | ; Hash Constants |
| 67 | ;***************************************************************************************** |
| 68 | #define HASH_MD5_IN0 0x01234567 |
| 69 | #define HASH_MD5_IN1 0x89abcdef |
| 70 | #define HASH_MD5_IN2 0xfedcba98 |
| 71 | #define HASH_MD5_IN3 0x76543210 |
| 72 | |
| 73 | #define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2 |
| 74 | #define HASH_SECURITY_BLOCK_CONTROL_INIT_MD5 ((1 << 4) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION) |
| 75 | |
| 76 | ;***************************************************************************************** |
| 77 | ; Hash related defines |
| 78 | ;***************************************************************************************** |
| 79 | #define hash_control 0x00(an_security_block) |
| 80 | #define hash_control_low 0x02(an_security_block) |
| 81 | #define hash_status 0x04(an_security_block) |
| 82 | |
| 83 | #define hash_input_0 0x30(an_security_block) |
| 84 | #define hash_input_1 0x34(an_security_block) |
| 85 | #define hash_input_2 0x38(an_security_block) |
| 86 | #define hash_input_3 0x3c(an_security_block) |
| 87 | #define hash_input_4 0x40(an_security_block) |
| 88 | |
| 89 | #define hash_output_0 0x70(an_security_block) |
| 90 | #define hash_output_0_low 0x72(an_security_block) |
| 91 | #define hash_output_1 0x74(an_security_block) |
| 92 | #define hash_output_1_low 0x76(an_security_block) |
| 93 | #define hash_output_2 0x78(an_security_block) |
| 94 | #define hash_output_2_low 0x7a(an_security_block) |
| 95 | #define hash_output_3 0x7c(an_security_block) |
| 96 | #define hash_output_3_low 0x7e(an_security_block) |
| 97 | |
| 98 | ;***************************************************************************************** |
| 99 | ; Assembly macros |
| 100 | ;***************************************************************************************** |
| 101 | ; C compiler reserves RP (A5) for return address during subroutine call. |
| 102 | ; Use RP to return to caller |
| 103 | .macro call_return_macro |
| 104 | calli RP, 0(RP) |
| 105 | .endm |
| 106 | |
| 107 | #if 0 |
| 108 | ;***************************************************************************************** |
| 109 | ; void md5_ip5k_init(void) |
| 110 | ; initialize the output registers of the hash module |
| 111 | ; |
| 112 | ;.section .text.md5_ip5k_init,"ax",@progbits |
| 113 | .section .text |
| 114 | .global _md5_ip5k_init |
| 115 | .func md5_ip5k_init, _md5_ip5k_init |
| 116 | |
| 117 | _md5_ip5k_init: |
| 118 | moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS |
| 119 | |
| 120 | movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5) |
| 121 | movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5) |
| 122 | |
| 123 | movei hash_output_0, #%hi(HASH_MD5_IN0) |
| 124 | movei hash_output_0_low, #%lo(HASH_MD5_IN0) |
| 125 | |
| 126 | movei hash_output_1, #%hi(HASH_MD5_IN1) |
| 127 | movei hash_output_1_low, #%lo(HASH_MD5_IN1) |
| 128 | |
| 129 | movei hash_output_2, #%hi(HASH_MD5_IN2) |
| 130 | movei hash_output_2_low, #%lo(HASH_MD5_IN2) |
| 131 | |
| 132 | movei hash_output_3, #%hi(HASH_MD5_IN3) |
| 133 | movei hash_output_3_low, #%lo(HASH_MD5_IN3) |
| 134 | |
| 135 | call_return_macro |
| 136 | .endfunc |
| 137 | #endif |
| 138 | |
| 139 | ;***************************************************************************************** |
| 140 | ; void md5_ip5k_init_digest(u32_t *hash_input) |
| 141 | ; initialize the output registers of the hash module |
| 142 | |
| 143 | ;.section .text.md5_ip5k_init_digest,"ax",@progbits |
| 144 | .section .text |
| 145 | .global _md5_ip5k_init_digest |
| 146 | .func md5_ip5k_init_digest, _md5_ip5k_init_digest |
| 147 | |
| 148 | _md5_ip5k_init_digest: |
| 149 | movea an_data_input, D0 |
| 150 | |
| 151 | moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS |
| 152 | |
| 153 | movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5) |
| 154 | movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5) |
| 155 | |
| 156 | move.4 hash_output_0, (an_data_input)4++ |
| 157 | move.4 hash_output_1, (an_data_input)4++ |
| 158 | move.4 hash_output_2, (an_data_input)4++ |
| 159 | move.4 hash_output_3, (an_data_input)4++ |
| 160 | |
| 161 | call_return_macro |
| 162 | .endfunc |
| 163 | |
| 164 | ;***************************************************************************************** |
| 165 | ; void md5_ip5k_transform(u32_t *data_input) |
| 166 | ; performs intermediate transformation step for the hash calculation |
| 167 | ; |
| 168 | ;.sect .text.md5_ip5k_transform,"ax",@progbits |
| 169 | .section .text |
| 170 | .global _md5_ip5k_transform |
| 171 | .func md5_ip5k_transform, _md5_ip5k_transform |
| 172 | |
| 173 | _md5_ip5k_transform: |
| 174 | movea an_data_input, D0 |
| 175 | |
| 176 | moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS |
| 177 | |
| 178 | ; Write the first 128bits (16 bytes) |
| 179 | move.4 hash_input_0, (an_data_input)4++ |
| 180 | move.4 hash_input_1, (an_data_input)4++ |
| 181 | move.4 hash_input_2, (an_data_input)4++ |
| 182 | move.4 hash_input_3, (an_data_input)4++ |
| 183 | move.4 hash_input_4, D0 |
| 184 | |
| 185 | move.4 hash_input_0, (an_data_input)4++ |
| 186 | move.4 hash_input_1, (an_data_input)4++ |
| 187 | move.4 hash_input_2, (an_data_input)4++ |
| 188 | move.4 hash_input_3, (an_data_input)4++ |
| 189 | move.4 hash_input_4, D0 |
| 190 | |
| 191 | move.4 hash_input_0, (an_data_input)4++ |
| 192 | move.4 hash_input_1, (an_data_input)4++ |
| 193 | move.4 hash_input_2, (an_data_input)4++ |
| 194 | move.4 hash_input_3, (an_data_input)4++ |
| 195 | move.4 hash_input_4, D0 |
| 196 | |
| 197 | move.4 hash_input_0, (an_data_input)4++ |
| 198 | move.4 hash_input_1, (an_data_input)4++ |
| 199 | move.4 hash_input_2, (an_data_input)4++ |
| 200 | move.4 hash_input_3, (an_data_input)4++ |
| 201 | move.4 hash_input_4, D0 |
| 202 | |
| 203 | pipe_flush 0 |
| 204 | |
| 205 | md5_ip5k_transform_wait: |
| 206 | ; wait for the module to calculate the output hash |
| 207 | btst hash_status, #0 |
| 208 | jmpne.f md5_ip5k_transform_wait |
| 209 | |
| 210 | call_return_macro |
| 211 | .endfunc |
| 212 | |
| 213 | ;***************************************************************************************** |
| 214 | ; void md5_ip5k_get_digest(u32_t *digest) |
| 215 | ; Return the hash of the input data |
| 216 | ; |
| 217 | ;.sect .text.md5_get_digest,"ax",@progbits |
| 218 | .section .text |
| 219 | .global _md5_ip5k_get_digest |
| 220 | .func md5_ip5k_get_digest, _md5_ip5k_get_digest |
| 221 | |
| 222 | _md5_ip5k_get_digest: |
| 223 | movea an_digest, D0 |
| 224 | |
| 225 | moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS |
| 226 | |
| 227 | ; we have finished |
| 228 | move.4 0(an_digest), hash_output_0 |
| 229 | move.4 4(an_digest), hash_output_1 |
| 230 | move.4 8(an_digest), hash_output_2 |
| 231 | move.4 12(an_digest), hash_output_3 |
| 232 | |
| 233 | call_return_macro |
| 234 | .endfunc |
| 235 | |