fix!: Remove cryptographic builtins (#396)

Cryptographic builtins are removed due to various reasons like FIPS
compliance. Users needing crypto builtins are encouraged to use
extensions.

Deprecated functions are also removed.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2025-04-16 12:24:19 -07:00
committed by GitHub
parent 667cb0d90f
commit 9e43bd9878
17 changed files with 155 additions and 1070 deletions
-123
View File
@@ -1,123 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
use crate::ast::{Expr, Ref};
use crate::builtins;
use crate::builtins::utils::{ensure_args_count, ensure_string};
use crate::lexer::Span;
use crate::value::Value;
use anyhow::{bail, Result};
use constant_time_eq::constant_time_eq;
use hmac::{Hmac, Mac};
use md5::{Digest, Md5};
use sha2::{Sha256, Sha512};
pub fn register(m: &mut builtins::BuiltinsMap<&'static str, builtins::BuiltinFcn>) {
m.insert("crypto.hmac.equal", (hmac_equal_fixed_time, 2));
m.insert("crypto.hmac.md5", (hmac_md5, 2));
m.insert("crypto.hmac.sha256", (hmac_sha256, 2));
m.insert("crypto.hmac.sha512", (hmac_sha512, 2));
m.insert("crypto.md5", (crypto_md5, 1));
m.insert("crypto.sha256", (crypto_sha256, 1));
}
fn hmac_equal_fixed_time(
span: &Span,
params: &[Ref<Expr>],
args: &[Value],
_strict: bool,
) -> Result<Value> {
let name = "crypto.hmac.equal";
ensure_args_count(span, name, params, args, 2)?;
let hmac1 = ensure_string(name, &params[0], &args[0])?;
let hmac2 = ensure_string(name, &params[1], &args[1])?;
Ok(Value::Bool(constant_time_eq(
hmac1.as_bytes(),
hmac2.as_bytes(),
)))
}
fn hmac_md5(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
let name = "crypto.hmac.md5";
ensure_args_count(span, name, params, args, 2)?;
let x = ensure_string(name, &params[0], &args[0])?;
let key = ensure_string(name, &params[1], &args[1])?;
let mut hmac = Hmac::<Md5>::new_from_slice(key.as_bytes())
.or_else(|_| bail!(span.error("failed to create hmac instance")))?;
hmac.update(x.as_bytes());
let result = hmac.finalize();
Ok(Value::String(hex::encode(result.into_bytes()).into()))
}
fn hmac_sha256(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
let name = "crypto.hmac.sha256";
ensure_args_count(span, name, params, args, 2)?;
let x = ensure_string(name, &params[0], &args[0])?;
let key = ensure_string(name, &params[1], &args[1])?;
let mut hmac = Hmac::<Sha256>::new_from_slice(key.as_bytes())
.or_else(|_| bail!(span.error("failed to create hmac instance")))?;
hmac.update(x.as_bytes());
let result = hmac.finalize();
Ok(Value::String(hex::encode(result.into_bytes()).into()))
}
fn hmac_sha512(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
let name = "crypto.hmac.sha512";
ensure_args_count(span, name, params, args, 2)?;
let x = ensure_string(name, &params[0], &args[0])?;
let key = ensure_string(name, &params[1], &args[1])?;
let mut hmac = Hmac::<Sha512>::new_from_slice(key.as_bytes())
.or_else(|_| bail!(span.error("failed to create hmac instance")))?;
hmac.update(x.as_bytes());
let result = hmac.finalize();
Ok(Value::String(hex::encode(result.into_bytes()).into()))
}
fn crypto_md5(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
let name = "crypto.md5";
ensure_args_count(span, name, params, args, 1)?;
let x = ensure_string(name, &params[0], &args[0])?;
let mut h = Md5::new();
h.update(x.as_bytes());
let result = h.finalize();
Ok(Value::String(hex::encode(result).into()))
}
fn crypto_sha256(
span: &Span,
params: &[Ref<Expr>],
args: &[Value],
_strict: bool,
) -> Result<Value> {
let name = "crypto.sha256";
ensure_args_count(span, name, params, args, 1)?;
let x = ensure_string(name, &params[0], &args[0])?;
let mut h = Sha256::new();
h.update(x.as_bytes());
let result = h.finalize();
Ok(Value::String(hex::encode(result).into()))
}
-133
View File
@@ -1,133 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
use crate::ast::{Expr, Ref};
use crate::builtins;
use crate::builtins::utils::{ensure_args_count, ensure_set};
use crate::builtins::BuiltinFcn;
use crate::lexer::Span;
use crate::value::Value;
use crate::*;
use anyhow::{bail, Result};
use lazy_static::lazy_static;
#[cfg(feature = "regex")]
use crate::builtins::regex::regex_match;
#[rustfmt::skip]
lazy_static! {
pub static ref DEPRECATED: builtins::BuiltinsMap<&'static str, BuiltinFcn> = {
let mut m : builtins::BuiltinsMap<&'static str, BuiltinFcn> = builtins::BuiltinsMap::new();
m.insert("all", (all, 1));
m.insert("any", (any, 1));
m.insert("cast_array", (cast_array, 1));
m.insert("cast_boolean", (cast_boolean, 1));
m.insert("cast_null", (cast_null, 1));
m.insert("cast_object", (cast_object, 1));
m.insert("cast_set", (cast_set, 1));
m.insert("cast_string", (cast_string, 1));
m.insert("set_diff", (set_diff, 2));
#[cfg(feature = "regex")]
m.insert("re_match", (regex_match, 2));
m
};
}
fn all(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
ensure_args_count(span, "all", params, args, 1)?;
Ok(Value::Bool(match &args[0] {
Value::Array(a) => a.iter().all(|i| i == &Value::Bool(true)),
Value::Set(a) => a.iter().all(|i| i == &Value::Bool(true)),
a => {
let span = params[0].span();
bail!(span.error(format!("`all` requires array/set argument. Got `{a}`.").as_str()))
}
}))
}
fn any(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
ensure_args_count(span, "any", params, args, 1)?;
Ok(Value::Bool(match &args[0] {
Value::Array(a) => a.iter().any(|i| i == &Value::Bool(true)),
Value::Set(a) => a.iter().any(|i| i == &Value::Bool(true)),
a => {
let span = params[0].span();
bail!(span.error(format!("`any` requires array/set argument. Got `{a}`.").as_str()))
}
}))
}
fn set_diff(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
let name = "set_diff";
ensure_args_count(span, name, params, args, 2)?;
let s1 = ensure_set(name, &params[0], args[0].clone())?;
let s2 = ensure_set(name, &params[1], args[1].clone())?;
Ok(Value::from_set(s1.difference(&s2).cloned().collect()))
}
fn cast_array(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool) -> Result<Value> {
let name = "cast_array";
ensure_args_count(span, name, params, args, 1)?;
match &args[0] {
Value::Array(_) => Ok(args[0].clone()),
Value::Set(s) => Ok(Value::from_array(s.iter().cloned().collect())),
_ if strict => bail!(params[0].span().error("array required")),
_ => Ok(Value::Undefined),
}
}
fn cast_boolean(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool) -> Result<Value> {
let name = "cast_boolean";
ensure_args_count(span, name, params, args, 1)?;
match &args[0] {
Value::Bool(_) => Ok(args[0].clone()),
_ if strict => bail!(params[0].span().error("boolean required")),
_ => Ok(Value::Undefined),
}
}
fn cast_null(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool) -> Result<Value> {
let name = "cast_null";
ensure_args_count(span, name, params, args, 1)?;
match &args[0] {
Value::Null => Ok(Value::Null),
_ if strict => bail!(params[0].span().error("null required")),
_ => Ok(Value::Undefined),
}
}
fn cast_object(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool) -> Result<Value> {
let name = "cast_object";
ensure_args_count(span, name, params, args, 1)?;
match &args[0] {
Value::Object(_) => Ok(args[0].clone()),
_ if strict => bail!(params[0].span().error("object required")),
_ => Ok(Value::Undefined),
}
}
fn cast_set(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool) -> Result<Value> {
let name = "cast_set";
ensure_args_count(span, name, params, args, 1)?;
match &args[0] {
Value::Set(_) => Ok(args[0].clone()),
Value::Array(a) => Ok(Value::from_set(a.iter().cloned().collect())),
_ if strict => bail!(params[0].span().error("set required")),
_ => Ok(Value::Undefined),
}
}
fn cast_string(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool) -> Result<Value> {
let name = "cast_string";
ensure_args_count(span, name, params, args, 1)?;
match &args[0] {
Value::String(_) => Ok(args[0].clone()),
_ if strict => bail!(params[0].span().error("string required")),
_ => Ok(Value::Undefined),
}
}
+5 -14
View File
@@ -7,10 +7,6 @@ mod bitwise;
pub mod comparison;
mod conversions;
#[cfg(feature = "crypto")]
mod crypto;
#[cfg(feature = "deprecated")]
pub mod deprecated;
mod encoding;
#[cfg(feature = "glob")]
mod glob;
@@ -51,14 +47,11 @@ use lazy_static::lazy_static;
pub type BuiltinFcn = (fn(&Span, &[Ref<Expr>], &[Value], bool) -> Result<Value>, u8);
#[cfg(feature = "deprecated")]
pub use deprecated::DEPRECATED;
#[rustfmt::skip]
lazy_static! {
pub static ref BUILTINS: BuiltinsMap<&'static str, BuiltinFcn> = {
let mut m : BuiltinsMap<&'static str, BuiltinFcn> = BuiltinsMap::new();
// comparison functions are directly called.
numbers::register(&mut m);
aggregates::register(&mut m);
@@ -66,16 +59,16 @@ lazy_static! {
sets::register(&mut m);
objects::register(&mut m);
strings::register(&mut m);
#[cfg(feature = "regex")]
regex::register(&mut m);
#[cfg(feature = "glob")]
glob::register(&mut m);
#[cfg(feature = "graph")]
graph::register(&mut m);
bitwise::register(&mut m);
conversions::register(&mut m);
//units::register(&mut m);
@@ -84,8 +77,6 @@ lazy_static! {
#[cfg(feature = "time")]
time::register(&mut m);
#[cfg(feature = "crypto")]
crypto::register(&mut m);
//graphql::register(&mut m);
#[cfg(feature = "http")]
http::register(&mut m);
-20
View File
@@ -55,10 +55,6 @@ fn opa_runtime(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool)
"base64",
#[cfg(feature = "base64url")]
"base64url",
#[cfg(feature = "crypto")]
"crypto",
#[cfg(feature = "deprecated")]
"deprecated",
#[cfg(feature = "glob")]
"glob",
#[cfg(feature = "graph")]
@@ -110,21 +106,5 @@ fn opa_runtime(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool)
),
);
#[cfg(feature = "deprecated")]
{
let mut deprecated: Vec<&&str> = builtins::deprecated::DEPRECATED.keys().collect();
deprecated.sort();
obj.insert(
Value::String("deprecated".into()),
Value::from_array(
deprecated
.iter()
.map(|f| Value::String(f.to_string().into()))
.collect(),
),
);
}
Ok(Value::from_map(obj))
}