| 1 | // Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | // Based off: https://github.com/golang/go/blob/master/src/crypto/aes |
| 5 | // Last commit: https://github.com/golang/go/commit/691a2d457ab1bf03bd46d4b69e0f93b8993c0055 |
| 6 | module aes |
| 7 | |
| 8 | import crypto.cipher |
| 9 | import crypto.internal.subtle |
| 10 | |
| 11 | // The AES block size in bytes. |
| 12 | pub const block_size = 16 |
| 13 | |
| 14 | // AesCipher represents an AES encryption using a particular key. |
| 15 | // It follows the API of golang's `cipher.Block` and is designed to |
| 16 | // handle only one block of data at a time. In most cases, you |
| 17 | // probably want to encrypt and decrypt using [[AesCbc](#AesCbc)] |
| 18 | struct AesCipher { |
| 19 | block_size int = block_size |
| 20 | mut: |
| 21 | enc []u32 |
| 22 | dec []u32 |
| 23 | } |
| 24 | |
| 25 | // free the resources taken by the AesCipher `c` |
| 26 | @[unsafe] |
| 27 | pub fn (mut c AesCipher) free() { |
| 28 | $if prealloc { |
| 29 | return |
| 30 | } |
| 31 | unsafe { |
| 32 | c.enc.free() |
| 33 | c.dec.free() |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | // new_cipher creates and returns a new [[AesCipher](#AesCipher)]. |
| 38 | // The key argument should be the AES key, |
| 39 | // either 16, 24, or 32 bytes to select |
| 40 | // AES-128, AES-192, or AES-256. |
| 41 | pub fn new_cipher(key []u8) cipher.Block { |
| 42 | k := key.len |
| 43 | match k { |
| 44 | 16, 24, 32 { |
| 45 | // break |
| 46 | } |
| 47 | else { |
| 48 | panic('crypto.aes: invalid key size ' + k.str()) |
| 49 | // return error('crypto.aes: invalid key size ' + k.str()) |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | // for now use generic version |
| 54 | return new_cipher_generic(key) |
| 55 | } |
| 56 | |
| 57 | // block_size returns the block size of the checksum in bytes. |
| 58 | pub fn (c &AesCipher) block_size() int { |
| 59 | return block_size |
| 60 | } |
| 61 | |
| 62 | // encrypt encrypts the first block of data in `src` to `dst`. |
| 63 | // NOTE: `dst` and `src` are both mutable for performance reasons. |
| 64 | // NOTE: `dst` and `src` must both be pre-allocated to the correct length. |
| 65 | // NOTE: `dst` and `src` may be the same (overlapping entirely). |
| 66 | pub fn (c &AesCipher) encrypt(mut dst []u8, src []u8) { |
| 67 | if src.len < block_size { |
| 68 | panic('crypto.aes: input not full block') |
| 69 | } |
| 70 | if dst.len < block_size { |
| 71 | panic('crypto.aes: output not full block') |
| 72 | } |
| 73 | // if subtle.inexact_overlap(dst[:block_size], src[:block_size]) { |
| 74 | if subtle.inexact_overlap(dst[..block_size], src[..block_size]) { |
| 75 | panic('crypto.aes: invalid buffer overlap') |
| 76 | } |
| 77 | // for now use generic version |
| 78 | encrypt_block_generic(c.enc, mut dst, src) |
| 79 | } |
| 80 | |
| 81 | // decrypt decrypts the first block of data in `src` to `dst`. |
| 82 | // NOTE: `dst` and `src` are both mutable for performance reasons. |
| 83 | // NOTE: `dst` and `src` must both be pre-allocated to the correct length. |
| 84 | // NOTE: `dst` and `src` may be the same (overlapping entirely). |
| 85 | pub fn (c &AesCipher) decrypt(mut dst []u8, src []u8) { |
| 86 | if src.len < block_size { |
| 87 | panic('crypto.aes: input not full block') |
| 88 | } |
| 89 | if dst.len < block_size { |
| 90 | panic('crypto.aes: output not full block') |
| 91 | } |
| 92 | if subtle.inexact_overlap(dst[..block_size], src[..block_size]) { |
| 93 | panic('crypto.aes: invalid buffer overlap') |
| 94 | } |
| 95 | // for now use generic version |
| 96 | decrypt_block_generic(c.dec, mut dst, src) |
| 97 | } |
| 98 | |