Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ovpn: implement key add/get/del/swap via netlink

This change introduces the netlink commands needed to add, get, delete
and swap keys for a specific peer.

Userspace is expected to use these commands to create, inspect (non
sensitive data only), destroy and rotate session keys for a specific
peer.

Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-19-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Antonio Quartulli and committed by
Paolo Abeni
203e2bf5 1d36a36f

+360 -4
+40
drivers/net/ovpn/crypto.c
··· 146 146 147 147 spin_unlock_bh(&cs->lock); 148 148 } 149 + 150 + /** 151 + * ovpn_crypto_config_get - populate keyconf object with non-sensible key data 152 + * @cs: the crypto state to extract the key data from 153 + * @slot: the specific slot to inspect 154 + * @keyconf: the output object to populate 155 + * 156 + * Return: 0 on success or a negative error code otherwise 157 + */ 158 + int ovpn_crypto_config_get(struct ovpn_crypto_state *cs, 159 + enum ovpn_key_slot slot, 160 + struct ovpn_key_config *keyconf) 161 + { 162 + struct ovpn_crypto_key_slot *ks; 163 + int idx; 164 + 165 + switch (slot) { 166 + case OVPN_KEY_SLOT_PRIMARY: 167 + idx = cs->primary_idx; 168 + break; 169 + case OVPN_KEY_SLOT_SECONDARY: 170 + idx = !cs->primary_idx; 171 + break; 172 + default: 173 + return -EINVAL; 174 + } 175 + 176 + rcu_read_lock(); 177 + ks = rcu_dereference(cs->slots[idx]); 178 + if (!ks) { 179 + rcu_read_unlock(); 180 + return -ENOENT; 181 + } 182 + 183 + keyconf->cipher_alg = ovpn_aead_crypto_alg(ks); 184 + keyconf->key_id = ks->key_id; 185 + rcu_read_unlock(); 186 + 187 + return 0; 188 + }
+4
drivers/net/ovpn/crypto.h
··· 136 136 137 137 void ovpn_crypto_key_slots_swap(struct ovpn_crypto_state *cs); 138 138 139 + int ovpn_crypto_config_get(struct ovpn_crypto_state *cs, 140 + enum ovpn_key_slot slot, 141 + struct ovpn_key_config *keyconf); 142 + 139 143 #endif /* _NET_OVPN_OVPNCRYPTO_H_ */
+17
drivers/net/ovpn/crypto_aead.c
··· 364 364 ovpn_aead_crypto_key_slot_destroy(ks); 365 365 return ERR_PTR(ret); 366 366 } 367 + 368 + enum ovpn_cipher_alg ovpn_aead_crypto_alg(struct ovpn_crypto_key_slot *ks) 369 + { 370 + const char *alg_name; 371 + 372 + if (!ks->encrypt) 373 + return OVPN_CIPHER_ALG_NONE; 374 + 375 + alg_name = crypto_tfm_alg_name(crypto_aead_tfm(ks->encrypt)); 376 + 377 + if (!strcmp(alg_name, ALG_NAME_AES)) 378 + return OVPN_CIPHER_ALG_AES_GCM; 379 + else if (!strcmp(alg_name, ALG_NAME_CHACHAPOLY)) 380 + return OVPN_CIPHER_ALG_CHACHA20_POLY1305; 381 + else 382 + return OVPN_CIPHER_ALG_NONE; 383 + }
+2
drivers/net/ovpn/crypto_aead.h
··· 24 24 ovpn_aead_crypto_key_slot_new(const struct ovpn_key_config *kc); 25 25 void ovpn_aead_crypto_key_slot_destroy(struct ovpn_crypto_key_slot *ks); 26 26 27 + enum ovpn_cipher_alg ovpn_aead_crypto_alg(struct ovpn_crypto_key_slot *ks); 28 + 27 29 #endif /* _NET_OVPN_OVPNAEAD_H_ */
+297 -4
drivers/net/ovpn/netlink.c
··· 17 17 #include "netlink.h" 18 18 #include "netlink-gen.h" 19 19 #include "bind.h" 20 + #include "crypto.h" 20 21 #include "peer.h" 21 22 #include "socket.h" 22 23 ··· 791 790 return ret; 792 791 } 793 792 793 + static int ovpn_nl_get_key_dir(struct genl_info *info, struct nlattr *key, 794 + enum ovpn_cipher_alg cipher, 795 + struct ovpn_key_direction *dir) 796 + { 797 + struct nlattr *attrs[OVPN_A_KEYDIR_MAX + 1]; 798 + int ret; 799 + 800 + ret = nla_parse_nested(attrs, OVPN_A_KEYDIR_MAX, key, 801 + ovpn_keydir_nl_policy, info->extack); 802 + if (ret) 803 + return ret; 804 + 805 + switch (cipher) { 806 + case OVPN_CIPHER_ALG_AES_GCM: 807 + case OVPN_CIPHER_ALG_CHACHA20_POLY1305: 808 + if (NL_REQ_ATTR_CHECK(info->extack, key, attrs, 809 + OVPN_A_KEYDIR_CIPHER_KEY) || 810 + NL_REQ_ATTR_CHECK(info->extack, key, attrs, 811 + OVPN_A_KEYDIR_NONCE_TAIL)) 812 + return -EINVAL; 813 + 814 + dir->cipher_key = nla_data(attrs[OVPN_A_KEYDIR_CIPHER_KEY]); 815 + dir->cipher_key_size = nla_len(attrs[OVPN_A_KEYDIR_CIPHER_KEY]); 816 + 817 + /* These algorithms require a 96bit nonce, 818 + * Construct it by combining 4-bytes packet id and 819 + * 8-bytes nonce-tail from userspace 820 + */ 821 + dir->nonce_tail = nla_data(attrs[OVPN_A_KEYDIR_NONCE_TAIL]); 822 + dir->nonce_tail_size = nla_len(attrs[OVPN_A_KEYDIR_NONCE_TAIL]); 823 + break; 824 + default: 825 + NL_SET_ERR_MSG_MOD(info->extack, "unsupported cipher"); 826 + return -EINVAL; 827 + } 828 + 829 + return 0; 830 + } 831 + 832 + /** 833 + * ovpn_nl_key_new_doit - configure a new key for the specified peer 834 + * @skb: incoming netlink message 835 + * @info: genetlink metadata 836 + * 837 + * This function allows the user to install a new key in the peer crypto 838 + * state. 839 + * Each peer has two 'slots', namely 'primary' and 'secondary', where 840 + * keys can be installed. The key in the 'primary' slot is used for 841 + * encryption, while both keys can be used for decryption by matching the 842 + * key ID carried in the incoming packet. 843 + * 844 + * The user is responsible for rotating keys when necessary. The user 845 + * may fetch peer traffic statistics via netlink in order to better 846 + * identify the right time to rotate keys. 847 + * The renegotiation follows these steps: 848 + * 1. a new key is computed by the user and is installed in the 'secondary' 849 + * slot 850 + * 2. at user discretion (usually after a predetermined time) 'primary' and 851 + * 'secondary' contents are swapped and the new key starts being used for 852 + * encryption, while the old key is kept around for decryption of late 853 + * packets. 854 + * 855 + * Return: 0 on success or a negative error code otherwise. 856 + */ 794 857 int ovpn_nl_key_new_doit(struct sk_buff *skb, struct genl_info *info) 795 858 { 796 - return -EOPNOTSUPP; 859 + struct nlattr *attrs[OVPN_A_KEYCONF_MAX + 1]; 860 + struct ovpn_priv *ovpn = info->user_ptr[0]; 861 + struct ovpn_peer_key_reset pkr; 862 + struct ovpn_peer *peer; 863 + u32 peer_id; 864 + int ret; 865 + 866 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF)) 867 + return -EINVAL; 868 + 869 + ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX, 870 + info->attrs[OVPN_A_KEYCONF], 871 + ovpn_keyconf_nl_policy, info->extack); 872 + if (ret) 873 + return ret; 874 + 875 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 876 + OVPN_A_KEYCONF_PEER_ID)) 877 + return -EINVAL; 878 + 879 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 880 + OVPN_A_KEYCONF_SLOT) || 881 + NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 882 + OVPN_A_KEYCONF_KEY_ID) || 883 + NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 884 + OVPN_A_KEYCONF_CIPHER_ALG) || 885 + NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 886 + OVPN_A_KEYCONF_ENCRYPT_DIR) || 887 + NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 888 + OVPN_A_KEYCONF_DECRYPT_DIR)) 889 + return -EINVAL; 890 + 891 + pkr.slot = nla_get_u32(attrs[OVPN_A_KEYCONF_SLOT]); 892 + pkr.key.key_id = nla_get_u32(attrs[OVPN_A_KEYCONF_KEY_ID]); 893 + pkr.key.cipher_alg = nla_get_u32(attrs[OVPN_A_KEYCONF_CIPHER_ALG]); 894 + 895 + ret = ovpn_nl_get_key_dir(info, attrs[OVPN_A_KEYCONF_ENCRYPT_DIR], 896 + pkr.key.cipher_alg, &pkr.key.encrypt); 897 + if (ret < 0) 898 + return ret; 899 + 900 + ret = ovpn_nl_get_key_dir(info, attrs[OVPN_A_KEYCONF_DECRYPT_DIR], 901 + pkr.key.cipher_alg, &pkr.key.decrypt); 902 + if (ret < 0) 903 + return ret; 904 + 905 + peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]); 906 + peer = ovpn_peer_get_by_id(ovpn, peer_id); 907 + if (!peer) { 908 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 909 + "no peer with id %u to set key for", 910 + peer_id); 911 + return -ENOENT; 912 + } 913 + 914 + ret = ovpn_crypto_state_reset(&peer->crypto, &pkr); 915 + if (ret < 0) { 916 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 917 + "cannot install new key for peer %u", 918 + peer_id); 919 + goto out; 920 + } 921 + 922 + netdev_dbg(ovpn->dev, "new key installed (id=%u) for peer %u\n", 923 + pkr.key.key_id, peer_id); 924 + out: 925 + ovpn_peer_put(peer); 926 + return ret; 927 + } 928 + 929 + static int ovpn_nl_send_key(struct sk_buff *skb, const struct genl_info *info, 930 + u32 peer_id, enum ovpn_key_slot slot, 931 + const struct ovpn_key_config *keyconf) 932 + { 933 + struct nlattr *attr; 934 + void *hdr; 935 + 936 + hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, &ovpn_nl_family, 937 + 0, OVPN_CMD_KEY_GET); 938 + if (!hdr) 939 + return -ENOBUFS; 940 + 941 + attr = nla_nest_start(skb, OVPN_A_KEYCONF); 942 + if (!attr) 943 + goto err; 944 + 945 + if (nla_put_u32(skb, OVPN_A_KEYCONF_PEER_ID, peer_id)) 946 + goto err; 947 + 948 + if (nla_put_u32(skb, OVPN_A_KEYCONF_SLOT, slot) || 949 + nla_put_u32(skb, OVPN_A_KEYCONF_KEY_ID, keyconf->key_id) || 950 + nla_put_u32(skb, OVPN_A_KEYCONF_CIPHER_ALG, keyconf->cipher_alg)) 951 + goto err; 952 + 953 + nla_nest_end(skb, attr); 954 + genlmsg_end(skb, hdr); 955 + 956 + return 0; 957 + err: 958 + genlmsg_cancel(skb, hdr); 959 + return -EMSGSIZE; 797 960 } 798 961 799 962 int ovpn_nl_key_get_doit(struct sk_buff *skb, struct genl_info *info) 800 963 { 801 - return -EOPNOTSUPP; 964 + struct nlattr *attrs[OVPN_A_KEYCONF_MAX + 1]; 965 + struct ovpn_priv *ovpn = info->user_ptr[0]; 966 + struct ovpn_key_config keyconf = { 0 }; 967 + enum ovpn_key_slot slot; 968 + struct ovpn_peer *peer; 969 + struct sk_buff *msg; 970 + u32 peer_id; 971 + int ret; 972 + 973 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF)) 974 + return -EINVAL; 975 + 976 + ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX, 977 + info->attrs[OVPN_A_KEYCONF], 978 + ovpn_keyconf_nl_policy, info->extack); 979 + if (ret) 980 + return ret; 981 + 982 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 983 + OVPN_A_KEYCONF_PEER_ID)) 984 + return -EINVAL; 985 + 986 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 987 + OVPN_A_KEYCONF_SLOT)) 988 + return -EINVAL; 989 + 990 + peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]); 991 + peer = ovpn_peer_get_by_id(ovpn, peer_id); 992 + if (!peer) { 993 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 994 + "cannot find peer with id %u", peer_id); 995 + return -ENOENT; 996 + } 997 + 998 + slot = nla_get_u32(attrs[OVPN_A_KEYCONF_SLOT]); 999 + 1000 + ret = ovpn_crypto_config_get(&peer->crypto, slot, &keyconf); 1001 + if (ret < 0) { 1002 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 1003 + "cannot extract key from slot %u for peer %u", 1004 + slot, peer_id); 1005 + goto err; 1006 + } 1007 + 1008 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1009 + if (!msg) { 1010 + ret = -ENOMEM; 1011 + goto err; 1012 + } 1013 + 1014 + ret = ovpn_nl_send_key(msg, info, peer->id, slot, &keyconf); 1015 + if (ret < 0) { 1016 + nlmsg_free(msg); 1017 + goto err; 1018 + } 1019 + 1020 + ret = genlmsg_reply(msg, info); 1021 + err: 1022 + ovpn_peer_put(peer); 1023 + return ret; 802 1024 } 803 1025 804 1026 int ovpn_nl_key_swap_doit(struct sk_buff *skb, struct genl_info *info) 805 1027 { 806 - return -EOPNOTSUPP; 1028 + struct ovpn_priv *ovpn = info->user_ptr[0]; 1029 + struct nlattr *attrs[OVPN_A_PEER_MAX + 1]; 1030 + struct ovpn_peer *peer; 1031 + u32 peer_id; 1032 + int ret; 1033 + 1034 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF)) 1035 + return -EINVAL; 1036 + 1037 + ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX, 1038 + info->attrs[OVPN_A_KEYCONF], 1039 + ovpn_keyconf_nl_policy, info->extack); 1040 + if (ret) 1041 + return ret; 1042 + 1043 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 1044 + OVPN_A_KEYCONF_PEER_ID)) 1045 + return -EINVAL; 1046 + 1047 + peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]); 1048 + peer = ovpn_peer_get_by_id(ovpn, peer_id); 1049 + if (!peer) { 1050 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 1051 + "no peer with id %u to swap keys for", 1052 + peer_id); 1053 + return -ENOENT; 1054 + } 1055 + 1056 + ovpn_crypto_key_slots_swap(&peer->crypto); 1057 + ovpn_peer_put(peer); 1058 + 1059 + return 0; 807 1060 } 808 1061 809 1062 int ovpn_nl_key_del_doit(struct sk_buff *skb, struct genl_info *info) 810 1063 { 811 - return -EOPNOTSUPP; 1064 + struct nlattr *attrs[OVPN_A_KEYCONF_MAX + 1]; 1065 + struct ovpn_priv *ovpn = info->user_ptr[0]; 1066 + enum ovpn_key_slot slot; 1067 + struct ovpn_peer *peer; 1068 + u32 peer_id; 1069 + int ret; 1070 + 1071 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF)) 1072 + return -EINVAL; 1073 + 1074 + ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX, 1075 + info->attrs[OVPN_A_KEYCONF], 1076 + ovpn_keyconf_nl_policy, info->extack); 1077 + if (ret) 1078 + return ret; 1079 + 1080 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 1081 + OVPN_A_KEYCONF_PEER_ID)) 1082 + return -EINVAL; 1083 + 1084 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs, 1085 + OVPN_A_KEYCONF_SLOT)) 1086 + return -EINVAL; 1087 + 1088 + peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]); 1089 + slot = nla_get_u32(attrs[OVPN_A_KEYCONF_SLOT]); 1090 + 1091 + peer = ovpn_peer_get_by_id(ovpn, peer_id); 1092 + if (!peer) { 1093 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 1094 + "no peer with id %u to delete key for", 1095 + peer_id); 1096 + return -ENOENT; 1097 + } 1098 + 1099 + ovpn_crypto_key_slot_delete(&peer->crypto, slot); 1100 + ovpn_peer_put(peer); 1101 + 1102 + return 0; 812 1103 } 813 1104 814 1105 /**