tstdvd.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:8k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.  * tstdvd.c
  3.  *
  4.  * Example program showing usage of DVD CSS ioctls
  5.  *
  6.  * Copyright (C) 1999 Andrew T. Veliath <andrewtv@usa.net>
  7.  * See http://www.rpi.edu/~veliaa/linux-dvd for more info.
  8.  */
  9. /*
  10.  * If supplied with one parameter it gets the disk key and
  11.  * saves it to a file.  If supplied with a second parameter
  12.  * (a LBA) then it gets the title key for the supplied LBA.
  13.  *
  14.  * When getting the disk key,  only the first 10 bytes of it
  15.  * are printed.  The whole key is written to the file.
  16.  */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <time.h>
  21. #include <unistd.h>
  22. #include <fcntl.h>
  23. #include <sys/ioctl.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <sys/types.h>
  27. #include <errno.h>
  28. #if defined(__OpenBSD__)
  29. # include <sys/dvdio.h>
  30. #elif defined(__linux__)
  31. # include <linux/cdrom.h>
  32. #else
  33. # error "Need the DVD ioctls"
  34. #endif
  35. #include "css-auth.h"
  36. byte Challenge[10];
  37. struct block Key1;
  38. struct block Key2;
  39. struct block KeyCheck;
  40. byte DiscKey[10];
  41. int varient = -1;
  42. void print_challenge(const byte *chal)
  43. {
  44. int i;
  45. for (i = 0; i < 10; ++i)
  46. printf(" %02X", chal[9-i] & 0xff);
  47. }
  48. void print_key(const byte *key)
  49. {
  50. int i;
  51. for (i = 0; i < 5; ++i)
  52. printf(" %02X", key[4-i] & 0xff);
  53. }
  54. void print_five(const byte *key)
  55. {
  56. int i;
  57. for (i = 0; i < 5; ++i)
  58. printf(" %02X", key[i] & 0xff);
  59. }
  60. int authenticate_drive(const byte *key)
  61. {
  62. int i;
  63. for (i=0; i<5; i++)
  64. Key1.b[i] = key[4-i];
  65. for (i = 0; i < 32; ++i)
  66. {
  67. CryptKey1(i, Challenge, &KeyCheck);
  68. if (memcmp(KeyCheck.b, Key1.b, 5)==0)
  69. {
  70. varient = i;
  71. printf("Drive Authentic - using varient %dn", i);
  72. return 1;
  73. }
  74. }
  75. if (varient == -1)
  76. printf("Drive would not Authenticaten");
  77. return 0;
  78. }
  79. int GetDiscKey(int fd, int agid, char *key)
  80. {
  81. dvd_struct s;
  82. int index, fdd;
  83. s.type = DVD_STRUCT_DISCKEY;
  84. s.disckey.agid = agid;
  85. memset(s.disckey.value, 0, 2048);
  86. if (ioctl(fd, DVD_READ_STRUCT, &s)<0)
  87. {
  88. printf("Could not read Disc Keyn");
  89. return 0;
  90. }
  91. printf ("Received Disc Key:t");
  92. for (index=0; index<sizeof s.disckey.value; index++)
  93. s.disckey.value[index] ^= key[4 - (index%5)];
  94. for (index=0; index<10; index++) {
  95. printf("%02X ", s.disckey.value[index]);
  96. }
  97. printf ("n");
  98. fdd = open("disk-key", O_WRONLY|O_TRUNC|O_CREAT, 0644);
  99. if (fdd < 0)
  100. printf("Can't create "disk-key"n");
  101. else {
  102. if (write(fdd, s.disckey.value, 2048) != 2048)
  103. printf("Can't write "disk-key"n");
  104. close(fdd);
  105. }
  106. return 1;
  107. }
  108. int GetTitleKey(int fd, int agid, int lba, char *key)
  109. {
  110. dvd_authinfo ai;
  111. int i, fdd;
  112. ai.type = DVD_LU_SEND_TITLE_KEY;
  113. ai.lstk.agid = agid;
  114. ai.lstk.lba = lba;
  115. if (ioctl(fd, DVD_AUTH, &ai)) {
  116. printf("GetTitleKey failedn");
  117. return 0;
  118. }
  119. printf ("Received Title Key:t");
  120. for (i = 0; i < 5; ++i) {
  121. ai.lstk.title_key[i] ^= key[4 - (i%5)];
  122. printf("%02X ", ai.lstk.title_key[i]);
  123. }
  124. putchar('n');
  125. printf(" CPM=%d, CP_SEC=%d, CGMS=%dn", ai.lstk.cpm, ai.lstk.cp_sec, ai.lstk.cgms);
  126. fdd = open("title-key", O_WRONLY|O_TRUNC|O_CREAT, 0644);
  127. if (fdd < 0)
  128. printf("Can't create "title-key"n");
  129. else {
  130. if (write(fdd, ai.lstk.title_key, 5) != 5)
  131. printf("Can't write "title-key"n");
  132. close(fdd);
  133. }
  134. return 1;
  135. }
  136. int GetASF(int fd)
  137. {
  138. dvd_authinfo ai;
  139. ai.type = DVD_LU_SEND_ASF;
  140. ai.lsasf.agid = 0;
  141. ai.lsasf.asf = 0;
  142. if (ioctl(fd, DVD_AUTH, &ai)) {
  143. printf("GetASF failedn");
  144. return 0;
  145. }
  146. printf("%sAuthenticatedn", (ai.lsasf.asf) ? "" : "not ");
  147. return 1;
  148. }
  149. /* Simulation of a non-CSS compliant host (i.e. the authentication fails,
  150.  * but idea is here for a real CSS compliant authentication scheme). */
  151. int
  152. hostauth (dvd_authinfo *ai)
  153. {
  154. int i;
  155. switch (ai->type) {
  156. /* Host data receive (host changes state) */
  157. case DVD_LU_SEND_AGID:
  158. printf("AGID %dn", ai->lsa.agid);
  159. ai->type = DVD_HOST_SEND_CHALLENGE;
  160. break;
  161. case DVD_LU_SEND_KEY1:
  162. printf("LU sent key1: "); print_key(ai->lsk.key); printf("n");
  163. if (!authenticate_drive(ai->lsk.key)) {
  164. ai->type = DVD_AUTH_FAILURE;
  165. return -EINVAL;
  166. }
  167. ai->type = DVD_LU_SEND_CHALLENGE;
  168. break;
  169. case DVD_LU_SEND_CHALLENGE:
  170. for (i = 0; i < 10; ++i)
  171. Challenge[i] = ai->hsc.chal[9-i];
  172. printf("LU sent challenge: "); print_challenge(Challenge); printf("n");
  173. CryptKey2(varient, Challenge, &Key2);
  174. ai->type = DVD_HOST_SEND_KEY2;
  175. break;
  176. /* Host data send */
  177. case DVD_HOST_SEND_CHALLENGE:
  178. for (i = 0; i < 10; ++i)
  179. ai->hsc.chal[9-i] = Challenge[i];
  180. printf("Host sending challenge: "); print_challenge(Challenge); printf("n");
  181. /* Returning data, let LU change state */
  182. break;
  183. case DVD_HOST_SEND_KEY2:
  184. for (i = 0; i < 5; ++i)
  185. ai->hsk.key[4-i] = Key2.b[i];
  186. printf("Host sending key 2: "); print_key(Key2.b); printf("n");
  187. /* Returning data, let LU change state */
  188. break;
  189. default:
  190. printf("Got invalid state %dn", ai->type);
  191. return -EINVAL;
  192. }
  193. return 0;
  194. }
  195. int authenticate(int fd, int title, int lba)
  196. {
  197. dvd_authinfo ai;
  198. dvd_struct dvds;
  199. int i, rv, tries, agid;
  200. memset(&ai, 0, sizeof (ai));
  201. memset(&dvds, 0, sizeof (dvds));
  202. GetASF(fd);
  203. /* Init sequence, request AGID */
  204. for (tries = 1, rv = -1; rv == -1 && tries < 4; ++tries) {
  205. printf("Request AGID [%d]...t", tries);
  206. ai.type = DVD_LU_SEND_AGID;
  207. ai.lsa.agid = 0;
  208. rv = ioctl(fd, DVD_AUTH, &ai);
  209. if (rv == -1) {
  210. perror("N/A, invalidating");
  211. ai.type = DVD_INVALIDATE_AGID;
  212. ai.lsa.agid = 0;
  213. ioctl(fd, DVD_AUTH, &ai);
  214. }
  215. }
  216. if (tries == 4) {
  217. printf("Cannot get AGIDn");
  218. return -1;
  219. }
  220. for (i = 0; i < 10; ++i)
  221. Challenge[i] = i;
  222. /* Send AGID to host */
  223. if (hostauth(&ai) < 0) {
  224. printf("Send AGID to host failedn");
  225. return -1;
  226. }
  227. /* Get challenge from host */
  228. if (hostauth(&ai) < 0) {
  229. printf("Get challenge from host failedn");
  230. return -1;
  231. }
  232. agid = ai.lsa.agid;
  233. /* Send challenge to LU */
  234. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  235. printf("Send challenge to LU failedn");
  236. return -1;
  237. }
  238. /* Get key1 from LU */
  239. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  240. printf("Get key1 from LU failedn");
  241. return -1;
  242. }
  243. /* Send key1 to host */
  244. if (hostauth(&ai) < 0) {
  245. printf("Send key1 to host failedn");
  246. return -1;
  247. }
  248. /* Get challenge from LU */
  249. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  250. printf("Get challenge from LU failedn");
  251. return -1;
  252. }
  253. /* Send challenge to host */
  254. if (hostauth(&ai) < 0) {
  255. printf("Send challenge to host failedn");
  256. return -1;
  257. }
  258. /* Get key2 from host */
  259. if (hostauth(&ai) < 0) {
  260. printf("Get key2 from host failedn");
  261. return -1;
  262. }
  263. /* Send key2 to LU */
  264. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  265. printf("Send key2 to LU failed (expected)n");
  266. return -1;
  267. }
  268. if (ai.type == DVD_AUTH_ESTABLISHED)
  269. printf("DVD is authenticatedn");
  270. else if (ai.type == DVD_AUTH_FAILURE)
  271. printf("DVD authentication failedn");
  272. memcpy(Challenge, Key1.b, 5);
  273. memcpy(Challenge+5, Key2.b, 5);
  274. CryptBusKey(varient, Challenge, &KeyCheck);
  275. printf("Received Session Key:t");
  276. for (i= 0; i< 5; i++)
  277. {
  278. printf("%02X ", KeyCheck.b[i]);
  279. }
  280. printf("n");
  281. GetASF(fd);
  282. if (title)
  283. GetTitleKey(fd, agid, lba, KeyCheck.b);
  284. else
  285. GetDiscKey(fd, agid, KeyCheck.b);
  286. GetASF(fd);
  287. return 0;
  288. }
  289. #ifndef FIBMAP
  290. #define FIBMAP 1
  291. #endif
  292. int path_to_lba(char *p)
  293. {
  294. int fd, lba = 0;
  295. if ((fd = open(p, O_RDONLY)) == -1) {
  296. perror("DVD vob file:");
  297. return 0;
  298. }
  299. if (ioctl(fd, FIBMAP, &lba) != 0) {
  300. perror("ioctl FIBMAP failed:");
  301. close(fd);
  302. return 0;
  303. }
  304. close(fd);
  305. return lba;
  306. }
  307. int main(int ac, char **av)
  308. {
  309. char *device;
  310. int fd, title = 0, lba = 0;
  311. if (ac < 2) {
  312. fprintf(stderr, "usage: tstdvd <device> [title_path]n");
  313. exit (1);
  314. }
  315. device = av[1];
  316. fd = open(device, O_RDONLY | O_NONBLOCK);
  317. if (fd < 0) {
  318. perror(device);
  319. exit(1);
  320. }
  321. if (ac == 3) {
  322. lba = path_to_lba(av[2]);
  323. title = 1;
  324. }
  325. authenticate(fd, title, lba);
  326. close(fd);
  327. return 0;
  328. }