Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example: crypto_accelerator object extern #53

Merged
merged 7 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions examples/include/crypto-accelerator.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
Copyright 2022 Advanced Micro Devices, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/// Crypto accelerator Extern definition

/// Crypto accelerator object is instantiated for each crypto algorithm
enum crypto_algorithm_e {
AES_GCM
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

/// Results from crypto accelerator
enum crypto_results_e {
SUCCESS,
AUTH_FAILURE,
HW_ERROR
}

/// special value to indicate that ICV is after the crypto payload
#define ICV_AFTER_PAYLOAD ((int<32>)-1)

/// The crypto_accelerator engine used in this example uses AES-GCM algorithm.
/// It is assumed to be agnostic to wire protocols i.e. does not understand protocol
/// specific headers like ESP, AH etc
///
/// The crypto accelerator does not modify the packet outside the payload area and ICV
/// Any wire-protocol header, trailer add/remove is handled by P4 pipeline
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today there is no standard way for a P4 pipeline to add/remove trailers at the end of long pipelines. The best workaround for short packets is to completely parse every byte of the short packet, and add/remove headers at the end, but that is not a good solution for packets that can be MTU in size.

Does your solution propose new capabilities in PNA and/or P4 to add/remove trailers?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternately, one could avoid the need for handling trailers in P4 pipeline completely by bundling together trailer add/remove into the encrypt/decrypt block logic.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The architecture can do anything it wants with trailers, that's how ethernet trailers actually work.
But you could add some externs to manipulate them. Symmetric with packet_in, but for trailers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple ways to add/manipulate trailers. This capability is useful in endpoints (PNA where protocols like ESP, RDMA do use trailers). One method can be - payload is defined as a variable length header. Parser can extract it (based on length computed from ipHeader.totalLen or any other means available). Deparser similarly can add it back to packet and then add trailer headers after it. This will not need any new support in P4 language.
Many targets and/or target compilers allow large extractions as long as control functions do not access the extracted bytes as in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For targets that need trailer processing by the accelerator, more methods can be added to this extern object for handling the trailers.. but those will be target specific, so I have not shown them here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Many targets and/or target compilers allow large extractions as long as control functions do not access the extracted bytes as in this case." That might be so, but I haven't used any of them. I am aware of several targets that do not support this way of accessing the end of MTU-sized packets, so while the P4 language spec definitely supports what you say in the language, there are a fair number of targets that won't do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessing/using trailers is done by more than one protocols so it is possible to define target-specific externs to add/remove/modify trailers that are generically useful outside IPSec ESP. Since the inline accelerators are after deparser, it is expected that trailers are added before packet reaches the accelerator. For crypto accelerators, trailers may be just payload that will be encrypted.
From the division of work perspective, I did not want to include this capability in the accelerator. In case it is required for specific targets, we can define target-specific methods for it as mentioned in earlier comment.

/// The engine does not perform additional functions such as anti-replay protection, it
/// is done in P4 pipeline
///
/// Crypto Engine takes the following inputs:
/// - key, iv, icv_location/size, enable_auth, auth_data (aka AAD), payload location
/// In some protocols AAD can be present in the packet (e.g ESP header), in that case AAD
/// can be specified as offset/len within the packet. Additional auth data
/// that is not part of the packet can also be provided
/// On encrypt operation, icv_location/size indicates that icv is inserted in the
/// packet at the specified packet offset
/// On decrypt operation, icv_location and size is used for auth validation
///
/// Example:
/// Encrypt operation:
/// Parameters passed : key, iv, icv_location/size, enable_auth, auth_data
/// Packet presented to the engine -
/// +------------------+--------------------------+-----------+
/// | Headers not to | Encryption protocol | payload |
/// | be Encrypted | headers (E.g Esp, Esp-IV)| |
/// +------------------+----------------------- -+-----------+
/// Packet after Encryption:
/// +------------------+--------------------------+-----------+-----------+
/// | Headers not to | Encryption protocol | Encrypted | ICV (opt) |
/// | be Encrypted | headers (E.g Esp, Esp-IV)| Payload | |
/// +------------------+--------------------------+-----------+-----------+
/// ICV can be inserted either before or right after the encrypted payload
/// as specified by icv_location/size
/// Results: Success, Hardware Error
///
/// Decrypt operation:
/// Parameters passed : key, iv, icv_location/size, enable_auth, auth_data
/// Packet presented to the engine -
/// +------------------+--------------------------+-----------+-----+
/// | Headers not to | Encryption protocol | Encrypted | ICV |
/// | Encrypted | headers (E.g Esp, Esp-IV)| Payload | |
/// +------------------+--------------------------+-----------+-----+
/// Packet after decrytion:
/// +------------------+--------------------------+-----------+-----+
/// | Headers not to | Encryption protocol | cleartext | ICV |
/// | Encrypted | headers (E.g Esp, Esp-IV)| Payload | |
/// +------------------+-- ----------------------+-----------+-----+
/// Results: Success, Auth Failure, Hardware Error
///
extern crypto_accelerator {
/// constructor
/// Some methods provided in this object may be specific to an algorithm used.
/// Compiler may be able to check and warn/error when incorrect methods are used
crypto_accelerator(crypto_algorithm_e algo);


// security association index for this security session
// Some implementations do not need it.. in that case this method should result in no-op
void set_sa_index<T>(in T sa_index);

// Set the initialization data based on protocol used. E.g. salt, random number/ counter for ipsec
void set_iv<T>(in T iv);
void set_key<T,S>(in T key, in S key_size); // 128, 192, 256

// The format of the auth data is not specified/mandated by this object definition
// If it is part of the packet, it can be specified using offset/len mothods below
void set_auth_data_offset<T>(in T offset);
void set_auth_data_len<T>(in T len);

// Alternatively: Following API can be used to consturct the auth_data and
// provide it to the engine.
void add_auth_data<H>(in H auth_data);

// Auth trailer aka ICV is added by the engine after doing encryption operation
// Specify icv location - when a wire protocol wants to add ICV in a specific location (e.g. AH)
// The following apis can be used to specify the location of ICV in the packet
// A special offset indicates ICV is after the payload
void set_icv_offset<T>(in T offset);
void set_icv_len<L>(in L len);

// setup payload to be encrypted/decrypted
void set_payload_offset<T>(in T offset);
void set_payload_len<T>(in T len);

// crypto accelerator runs at the end of the pipeline (after deparser), the following
// methods will enable the accelerator to run encrypt/decrypt operations
// enable_auth flag enables authentication check for decrypt. For encrypt operation,
// auth data computed, is added to specified icv_offset/len
void enable_encrypt<T>(in T enable_auth);
void enable_decrypt<T>(in T enable_auth);

// disable crypto engine. Between enable and disable methods,
// whichever method is called last overrides the previous calls
void disable();

// get results of the previous operation
crypto_results_e get_results();
}
Loading