1use foreign_types::{ForeignType, ForeignTypeRef};
9use libc::c_uint;
10use openssl_macros::corresponds;
11use std::fmt;
12use std::mem;
13use std::ptr;
14
15use crate::bn::{BigNum, BigNumRef};
16use crate::error::ErrorStack;
17use crate::ffi;
18use crate::pkey::{HasParams, HasPrivate, HasPublic, Private, Public};
19use crate::try_int;
20use crate::{cvt, cvt_p};
21
22generic_foreign_type_and_impl_send_sync! {
23 type CType = ffi::DSA;
24 fn drop = ffi::DSA_free;
25
26 pub struct Dsa<T>;
58 pub struct DsaRef<T>;
62}
63
64impl<T> Clone for Dsa<T> {
65 fn clone(&self) -> Dsa<T> {
66 (**self).to_owned()
67 }
68}
69
70impl<T> ToOwned for DsaRef<T> {
71 type Owned = Dsa<T>;
72
73 fn to_owned(&self) -> Dsa<T> {
74 unsafe {
75 ffi::DSA_up_ref(self.as_ptr());
76 Dsa::from_ptr(self.as_ptr())
77 }
78 }
79}
80
81impl<T> DsaRef<T>
82where
83 T: HasPublic,
84{
85 to_pem! {
86 #[corresponds(PEM_write_bio_DSA_PUBKEY)]
90 public_key_to_pem,
91 ffi::PEM_write_bio_DSA_PUBKEY
92 }
93
94 to_der! {
95 #[corresponds(i2d_DSA_PUBKEY)]
97 public_key_to_der,
98 ffi::i2d_DSA_PUBKEY
99 }
100
101 #[must_use]
103 pub fn pub_key(&self) -> &BigNumRef {
104 unsafe {
105 let mut pub_key = ptr::null();
106 DSA_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
107 BigNumRef::from_ptr(pub_key.cast_mut())
108 }
109 }
110}
111
112impl<T> DsaRef<T>
113where
114 T: HasPrivate,
115{
116 private_key_to_pem! {
117 #[corresponds(PEM_write_bio_DSAPrivateKey)]
121 private_key_to_pem,
122 #[corresponds(PEM_write_bio_DSAPrivateKey)]
126 private_key_to_pem_passphrase,
127 ffi::PEM_write_bio_DSAPrivateKey
128 }
129
130 #[must_use]
132 pub fn priv_key(&self) -> &BigNumRef {
133 unsafe {
134 let mut priv_key = ptr::null();
135 DSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
136 BigNumRef::from_ptr(priv_key.cast_mut())
137 }
138 }
139}
140
141impl<T> DsaRef<T>
142where
143 T: HasParams,
144{
145 #[corresponds(DSA_size)]
147 #[must_use]
148 pub fn size(&self) -> u32 {
149 unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
150 }
151
152 #[must_use]
154 pub fn p(&self) -> &BigNumRef {
155 unsafe {
156 let mut p = ptr::null();
157 DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
158 BigNumRef::from_ptr(p.cast_mut())
159 }
160 }
161
162 #[must_use]
164 pub fn q(&self) -> &BigNumRef {
165 unsafe {
166 let mut q = ptr::null();
167 DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
168 BigNumRef::from_ptr(q.cast_mut())
169 }
170 }
171
172 #[must_use]
174 pub fn g(&self) -> &BigNumRef {
175 unsafe {
176 let mut g = ptr::null();
177 DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
178 BigNumRef::from_ptr(g.cast_mut())
179 }
180 }
181}
182
183impl Dsa<Private> {
184 pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
194 ffi::init();
195 unsafe {
196 let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
197 cvt(ffi::DSA_generate_parameters_ex(
198 dsa.0,
199 c_uint::from(bits),
200 ptr::null(),
201 0,
202 ptr::null_mut(),
203 ptr::null_mut(),
204 ptr::null_mut(),
205 ))?;
206 cvt(ffi::DSA_generate_key(dsa.0))?;
207 Ok(dsa)
208 }
209 }
210
211 pub fn from_private_components(
217 p: BigNum,
218 q: BigNum,
219 g: BigNum,
220 priv_key: BigNum,
221 pub_key: BigNum,
222 ) -> Result<Dsa<Private>, ErrorStack> {
223 ffi::init();
224 unsafe {
225 let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
226 cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
227 mem::forget((p, q, g));
228 cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), priv_key.as_ptr()))?;
229 mem::forget((pub_key, priv_key));
230 Ok(dsa)
231 }
232 }
233}
234
235impl Dsa<Public> {
236 from_pem! {
237 #[corresponds(PEM_read_bio_DSA_PUBKEY)]
241 public_key_from_pem,
242 Dsa<Public>,
243 ffi::PEM_read_bio_DSA_PUBKEY
244 }
245
246 from_der! {
247 #[corresponds(d2i_DSA_PUBKEY)]
249 public_key_from_der,
250 Dsa<Public>,
251 ffi::d2i_DSA_PUBKEY,
252 ::libc::c_long
253 }
254
255 pub fn from_public_components(
260 p: BigNum,
261 q: BigNum,
262 g: BigNum,
263 pub_key: BigNum,
264 ) -> Result<Dsa<Public>, ErrorStack> {
265 ffi::init();
266 unsafe {
267 let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
268 cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
269 mem::forget((p, q, g));
270 cvt(DSA_set0_key(dsa.0, pub_key.into_ptr(), ptr::null_mut()))?;
271 Ok(dsa)
272 }
273 }
274}
275
276impl<T> fmt::Debug for Dsa<T> {
277 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 write!(f, "DSA")
279 }
280}
281
282use crate::ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
283
284#[cfg(test)]
285mod test {
286 use super::*;
287 use crate::bn::BigNumContext;
288
289 #[test]
290 pub fn test_generate() {
291 Dsa::generate(1024).unwrap();
292 }
293
294 #[test]
295 fn test_pubkey_generation() {
296 let dsa = Dsa::generate(1024).unwrap();
297 let p = dsa.p();
298 let g = dsa.g();
299 let priv_key = dsa.priv_key();
300 let pub_key = dsa.pub_key();
301 let mut ctx = BigNumContext::new().unwrap();
302 let mut calc = BigNum::new().unwrap();
303 calc.mod_exp(g, priv_key, p, &mut ctx).unwrap();
304 assert_eq!(&calc, pub_key);
305 }
306
307 #[test]
308 fn test_priv_key_from_parts() {
309 let p = BigNum::from_u32(283).unwrap();
310 let q = BigNum::from_u32(47).unwrap();
311 let g = BigNum::from_u32(60).unwrap();
312 let priv_key = BigNum::from_u32(15).unwrap();
313 let pub_key = BigNum::from_u32(207).unwrap();
314
315 let dsa = Dsa::from_private_components(p, q, g, priv_key, pub_key).unwrap();
316 assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
317 assert_eq!(dsa.priv_key(), &BigNum::from_u32(15).unwrap());
318 assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
319 assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
320 assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
321 }
322
323 #[test]
324 fn test_pub_key_from_parts() {
325 let p = BigNum::from_u32(283).unwrap();
326 let q = BigNum::from_u32(47).unwrap();
327 let g = BigNum::from_u32(60).unwrap();
328 let pub_key = BigNum::from_u32(207).unwrap();
329
330 let dsa = Dsa::from_public_components(p, q, g, pub_key).unwrap();
331 assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
332 assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
333 assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
334 assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
335 }
336
337 #[test]
338 #[allow(clippy::redundant_clone)]
339 fn clone() {
340 let key = Dsa::generate(2048).unwrap();
341 drop(key.clone());
342 }
343}