') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Implement AES backend for riscv using crypto extensions by silvanshade · Pull Request #399 · RustCrypto/block-ciphers · GitHub
Skip to content

Implement AES backend for riscv using crypto extensions - #399

Closed
silvanshade wants to merge 1 commit into
RustCrypto:masterfrom
silvanshade:feature/aes-riscv-crypto
Closed

Implement AES backend for riscv using crypto extensions#399
silvanshade wants to merge 1 commit into
RustCrypto:masterfrom
silvanshade:feature/aes-riscv-crypto

Conversation

@silvanshade

@silvanshadesilvanshade commented Jan 21, 2024

Copy link
Copy Markdown
Contributor

Continued from #397.

This PR implements AES for riscv64 using the scalar and vector crypto extensions.

The scalar implementation is complete, sans hazmat support.

The vector implementation is complete, sans hazmat support. I plan to make some further refinements and optimizations though.

Currently there's no easy way to auto-detect the RISC-V features so instead the implementation selection relies on the appropriate target-features being enabled (plus a cfg flags called target_feature_zvkned) since that is apparently too new to have it's own Rust target-feature.

For the vector implementation, I resorted to using the global_asm!. There are a few reasons for behind this:

First, Rust doesn't even have a way to represent scalable vectors yet so there's no clear way how to even encode the appropriate function signatures for this. It might be possible to do it somehow through an encoding using opaque types and a C-FFI API wrapping the C intrinsics, but that would be difficult just for this relatively limited use case.

There is some progress toward addressing this situation though: rust-lang/rust#118917

Secondly, there seem to be some problems with using certain RISC-V features with inline asm!. It may be related to this issue, which also affects global_asm!, but in the case of asm! the errors actually cause compilation to fail (whereas for global_asm! they just add noise, but can be silenced with the .architecture attribute). The feature in question is zvkned, and it may be that this causes a problem because Rust doesn't even expose this feature yet (which is why I'm using the cfg setting).

In any case, things work fine with global_asm!.

I don't have any real hardware that implements these extensions, so I don't have any useful information about benchmarks. If anyone has access to hardware that can run this it would be great to get some feedback about that (or any other issues).

One last thing to note, I think it might be worth considering extending the cipher API to account for VLA-style implementations.

For example, consider the vector implementation for AES-128:

fnencrypt_vla(keys:&RoundKeys<11>,mutdata:InOut<'_,'_,Block>,blocks:usize){let dst = data.get_out().as_mut_ptr();let src = data.get_in().as_ptr();let len = blocks *16;let key = keys.as_ptr().cast::<u32>();unsafe{aes_riscv_rv64_vector_encdec_aes128_encrypt(dst, src, len, key)};}fnencrypt1(keys:&RoundKeys<11>,mutdata:InOut<'_,'_,Block>){let data = unsafe{InOut::from_raw(
data.get_in().as_ptr().cast::<Block>(),
data.get_out().as_mut_ptr().cast::<Block>(),)};encrypt_vla(keys, data,1)}fnencrypt8(keys:&RoundKeys<11>,mutdata:InOut<'_,'_,Block8>){let data = unsafe{InOut::from_raw(
data.get_in().as_ptr().cast::<Block>(),
data.get_out().as_mut_ptr().cast::<Block>(),)};encrypt_vla(keys, data,8)}

Here you can see that the encrypt_vla function is the general case, which is N-ary (per blocks). The 1-block and 8-block cases are just special cases of this and entirely redundant.

Generally you would want to pass as many blocks as possible to encrypt_vla, which might be substantially larger than 8, depending on the size of the vector registers for the specific RISC-V platform.

What might be an appropriate API then would be to add a method to one of the traits which would query the implementation for a "block parallelism hint", which would indicate how many blocks would be optimal to pass to the codec. This hint method would in turn execute some of the RVV instructions to calculate what is the (current) maximum available length for processing.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@silvanshade