diff --git a/docs/references/ic-interface-spec/canister-interface.md b/docs/references/ic-interface-spec/canister-interface.md
index e342b8cc..aec0a0eb 100644
--- a/docs/references/ic-interface-spec/canister-interface.md
+++ b/docs/references/ic-interface-spec/canister-interface.md
@@ -986,7 +986,7 @@ These system calls return costs in Cycles, represented by 128 bits, which will b
- `ic0.cost_vetkd_derive_key(src : I, size : I, vetkd_curve: i32, dst : I) -> i32`; `I ∈ {i32, i64}`
These system calls accept a key name via a textual representation for the specific signing scheme / key of a given size stored in the heap memory starting at offset `src`. They also accept an `i32` with the following interpretations:
- - `ecdsa_curve: 0 → secp256k1`
+ - `ecdsa_curve: 0 → secp256k1, 1 → secp256r1`
- `algorithm: 0 → bip340secp256k1, 1 → ed25519`
- `vetkd_curve: 0 → bls12_381`
diff --git a/docs/references/ic-interface-spec/changelog.md b/docs/references/ic-interface-spec/changelog.md
index 7a85ae83..9013f7aa 100644
--- a/docs/references/ic-interface-spec/changelog.md
+++ b/docs/references/ic-interface-spec/changelog.md
@@ -8,6 +8,13 @@ sidebar:
## Changelog {#changelog}
+### 0.70.0 (2026-10-05) {$0_70_0}
+* New variant `secp256r1` of `ecdsa_curve`, selecting threshold ECDSA on the NIST P-256 curve in
+ `ecdsa_public_key` and `sign_with_ecdsa`. Key derivation follows SLIP-10 and signatures are encoded as
+ for `secp256k1`, the concatenation of the 32-byte big-endian encodings of r and s. The `ecdsa_curve`
+ argument of `ic0.cost_sign_with_ecdsa` accepts `1` for the new curve. As for any curve, the
+ availability of a particular `key_id` depends on the implementation.
+
### 0.69.0 (2026-09-28) {$0_69_0}
* New management canister endpoint `subnet_metrics` returning subnet-wide metrics for a
given subnet: the current block height, the number of canisters, the total canister
diff --git a/docs/references/ic-interface-spec/management-canister.md b/docs/references/ic-interface-spec/management-canister.md
index 1aa238f4..07beff55 100644
--- a/docs/references/ic-interface-spec/management-canister.md
+++ b/docs/references/ic-interface-spec/management-canister.md
@@ -475,7 +475,11 @@ This method can only be called by canisters, i.e., it cannot be called by extern
This method returns a [SEC1](https://www.secg.org/sec1-v2.pdf) encoded ECDSA public key for the given canister using the given derivation path. If the `canister_id` is unspecified, it will default to the canister id of the caller. The `derivation_path` is a vector of variable length byte strings. Each byte string may be of arbitrary length, including empty. The total number of byte strings in the `derivation_path` must be at most 255. The `key_id` is a struct specifying both a curve and a name. The availability of a particular `key_id` depends on the implementation.
-For curve `secp256k1`, the public key is derived using a generalization of BIP32 (see [ia.cr/2021/1330, Appendix D](https://ia.cr/2021/1330)). To derive (non-hardened) [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)-compatible public keys, each byte string (`blob`) in the `derivation_path` must be a 4-byte big-endian encoding of an unsigned integer less than 231. If the `derivation_path` contains a byte string that is not a 4-byte big-endian encoding of an unsigned integer less than 231, then a derived public key will be returned, but that key derivation process will not be compatible with the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) standard.
+The derivation depends on the key ID's `curve`:
+
+- For curve `secp256k1`, the public key is derived using a generalization of BIP32 (see [ia.cr/2021/1330, Appendix D](https://ia.cr/2021/1330)). To derive (non-hardened) [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)-compatible public keys, each byte string (`blob`) in the `derivation_path` must be a 4-byte big-endian encoding of an unsigned integer less than 231. If the `derivation_path` contains a byte string that is not a 4-byte big-endian encoding of an unsigned integer less than 231, then a derived public key will be returned, but that key derivation process will not be compatible with the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) standard.
+
+- For curve `secp256r1`, the public key is derived using the same generalization instantiated over NIST P-256, which is [SLIP-10](https://github.com/satoshilabs/slips/blob/master/slip-0010.md). To derive (non-hardened) [SLIP-10](https://github.com/satoshilabs/slips/blob/master/slip-0010.md)-compatible public keys, the same encoding requirement applies to every byte string (`blob`) in the `derivation_path`.
The return value is an extended public key consisting of an ECDSA `public_key`, encoded in [SEC1](https://www.secg.org/sec1-v2.pdf) compressed form, and a `chain_code`, which can be used to deterministically derive child keys of the `public_key`.
@@ -493,7 +497,7 @@ If the signing request returns a reject response whose reject code is `SYS_UNKNO
:::
-The signatures are encoded as the concatenation of the [SEC1](https://www.secg.org/sec1-v2.pdf) encodings of the two values r and s. For curve `secp256k1`, this corresponds to 32-byte big-endian encoding.
+The signatures are encoded as the concatenation of the [SEC1](https://www.secg.org/sec1-v2.pdf) encodings of the two values r and s. For curves `secp256k1` and `secp256r1`, this corresponds to 32-byte big-endian encoding.
This call requires that an ECDSA key with ID `key_id` was generated by the IC, the signing functionality for that key was enabled, and `message_hash` is 32 bytes long. Otherwise, the call is is rejected.
diff --git a/docs/references/management-canister.md b/docs/references/management-canister.md
index 37d87a1b..3c4e8526 100644
--- a/docs/references/management-canister.md
+++ b/docs/references/management-canister.md
@@ -353,12 +353,12 @@ Returns a SEC1-encoded ECDSA public key derived for the given canister and deriv
- **Parameters:**
- `canister_id` (`opt principal`): defaults to caller
- `derivation_path` (`vec blob`): up to 255 byte strings of arbitrary length
- - `key_id` (`record { curve : ecdsa_curve; name : text }`): currently supports `secp256k1`
+ - `key_id` (`record { curve : ecdsa_curve; name : text }`): the curve is `secp256k1` or `secp256r1` (NIST P-256); see [Deployed keys](../concepts/chain-key-cryptography.md#deployed-keys) for the keys available on mainnet
- **Returns:**
- `public_key` (`blob`): SEC1 compressed public key
- `chain_code` (`blob`): for deterministic child key derivation
-For `secp256k1`, key derivation uses a generalization of BIP-32. To derive BIP-32-compatible public keys, each entry in `derivation_path` must be a 4-byte big-endian unsigned integer less than 2^31.
+For `secp256k1`, key derivation uses a generalization of BIP-32. For `secp256r1`, it uses the same generalization instantiated over P-256, which is [SLIP-10](https://github.com/satoshilabs/slips/blob/master/slip-0010.md). To derive BIP-32-compatible (or, for `secp256r1`, SLIP-10-compatible) public keys, each entry in `derivation_path` must be a 4-byte big-endian unsigned integer less than 2^31.
### `sign_with_ecdsa`
@@ -370,7 +370,7 @@ Signs a message hash using threshold ECDSA. The corresponding public key can be
- `derivation_path` (`vec blob`)
- `key_id` (`record { curve : ecdsa_curve; name : text }`)
- **Returns:**
- - `signature` (`blob`): concatenation of SEC1-encoded `r` and `s` values (64 bytes for `secp256k1`)
+ - `signature` (`blob`): concatenation of SEC1-encoded `r` and `s` values (64 bytes for both `secp256k1` and `secp256r1`)
- **Cycles:** Must be explicitly attached to the call
> If the call returns a reject with code `SYS_UNKNOWN` or `CANISTER_ERROR`, the signature may still exist in the system. Do not assume the signature was not produced.
diff --git a/public/references/ic.did b/public/references/ic.did
index 8000333a..6cdd0ccc 100644
--- a/public/references/ic.did
+++ b/public/references/ic.did
@@ -154,6 +154,7 @@ type flexible_http_request_result = variant {
type ecdsa_curve = variant {
secp256k1;
+ secp256r1;
};
type vetkd_curve = variant {